> ## Documentation Index
> Fetch the complete documentation index at: https://stars-components.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# @wolfstar/schema

> Typed stars.config schema, defineConfig helper, and loader shared by @wolfstar/http-framework and @wolfstar/cli via a Nuxt-style split.

```bash npm theme={"system"}
npm install @wolfstar/schema
```

```bash pnpm theme={"system"}
pnpm add @wolfstar/schema
```

```bash yarn theme={"system"}
yarn add @wolfstar/schema
```

```bash bun theme={"system"}
bun add @wolfstar/schema
```

> [card] [npm](https://npmx.dev/package/@wolfstar/schema)

> [card] [Source](https://github.com/wolfstar-project/stars-components/tree/main/packages/schema)

## Description

`@wolfstar/schema` owns the typed `stars.config.*` schema, the `defineConfig` helper, and the loader that discovers,
validates, and resolves `stars.config.{ts,mts,cts,js,mjs,cjs}`. It sits between
[`@wolfstar/http-framework`](https://stars-components.js.org/documentation/packages/http-framework) and
[`@wolfstar/cli`](https://stars-components.js.org/documentation/packages/cli), the same way `@nuxt/schema` sits between `nuxt` and `@nuxt/cli`.
Both depend on it, and neither depends on the other.

The package is intentionally side-effect free: importing it from a `stars.config.ts` file never starts a bot or pulls
in the CLI runtime.

## When to use it

Most projects should keep importing `defineConfig` from `@wolfstar/http-framework/config`. The framework re-exports
this package's public surface unchanged, so existing configuration files keep working with no changes needed.

Depend on `@wolfstar/schema` directly when:

* You are building tooling that reads a `stars.config.*` without needing the framework runtime.
* You want the lightweight `@wolfstar/schema/config` entry point in your `stars.config.ts` (just `defineConfig`, no
  loader or diagnostics).

## Usage

The two entry points map to two different needs.

### Configuration files (`@wolfstar/schema/config`)

Use this in a project's `stars.config.ts`. It only exposes the `defineConfig` identity helper and the input types, so
importing it costs nothing at runtime:

```typescript theme={"system"}
// stars.config.ts
import { defineConfig } from '@wolfstar/schema/config';

export default defineConfig({});
```

### Tooling and programmatic loading (`@wolfstar/schema`)

The root entry point adds the discovery, validation, and resolution machinery. Use it when a tool needs to load a
project's resolved configuration:

```typescript theme={"system"}
import { loadStarsConfig } from '@wolfstar/schema';

const config = await loadStarsConfig({ cwd: process.cwd() });
console.log(config.entry, config.build.output);
```

`loadStarsConfig` discovers the config file, applies the built-in defaults, validates every option, and resolves all
paths to absolute ones. Invalid options raise a diagnostic whose `code`, `path`, `sources`, and `hint` describe the
problem — see [Configuration Errors](https://stars-components.js.org/documentation/errors/config.md) for the full catalog.

### Top-level module keys

`loadStarsConfig` does not reject a top-level key that is not built in. It may hold the options of a module that
declares it as its [`meta.configKey`](https://stars-components.js.org/documentation/packages/kit#reading-options-from-a-config-key), which the schema
cannot know before the modules load. `loadStarsConfig` keeps these keys, unvalidated, on `config.moduleOptions`.
`BUILT_IN_CONFIG_KEYS` lists the keys the schema owns.

The `stars` commands report any key that no installed module claimed once the modules are set up. To run the same check in a
tool that loads the configuration on its own, call `assertModuleOptionsClaimed`. Pass the `meta.configKey` values of
the modules the tool installed, or `[]` when it installs none:

```typescript theme={"system"}
import { assertModuleOptionsClaimed, loadStarsConfig } from '@wolfstar/schema';

const config = await loadStarsConfig({ cwd: process.cwd() });
assertModuleOptionsClaimed(config, []);
```

It throws [`UNKNOWN_OPTION`](https://stars-components.js.org/documentation/errors/config#unknown_option) for the first unclaimed key. Both helpers are
also exported by `@wolfstar/http-framework/config`. After the CLI sets up the modules, `config.runtime.configKeys`
lists the keys they claimed.

For type-only imports of the input and resolved shapes:

```typescript theme={"system"}
import type { StarsConfig, ResolvedStarsConfig, BuilderContext } from '@wolfstar/schema';
```

### Registering only modules

`future.compatibilityVersion: 7` is an opt-in preview that makes the configuration decide what registers. It includes
everything in version 6. In addition, the `@wolfstar/plugin-*` packages found in `package.json` are no longer
activated by their name: the CLI injects no `import "<name>/register"` into the entry. Only the modules in `modules`,
and the modules they install, are registered. A plugin that is not a module must be imported by the bot itself.

```typescript theme={"system"}
// stars.config.ts
import { defineConfig } from '@wolfstar/schema/config';

export default defineConfig({
	future: { compatibilityVersion: 7 },
	modules: ['@wolfstar/plugin-i18next/module']
});
```

Version 6 stays the default, and `LATEST_COMPATIBILITY_VERSION` does not point at 7. Tooling can compare
`config.future.compatibilityVersion` against the exported `MODULES_ONLY_VERSION` constant to know whether a project
registers only modules:

```typescript theme={"system"}
import { MODULES_ONLY_VERSION, loadStarsConfig } from '@wolfstar/schema';

const config = await loadStarsConfig({ cwd: process.cwd() });
const modulesOnly = config.future.compatibilityVersion >= MODULES_ONLY_VERSION;
```

On version 7, the `stars` commands warn with
[`PLUGINS_NOT_REGISTERED`](https://stars-components.js.org/documentation/errors/cli#plugins_not_registered) about an installed plugin that no module
covers. Below version 7, `stars info` lists those plugins in a **by name** row and `stars doctor` in a `plugins` check.
See [Registering only modules](https://stars-components.js.org/documentation/guide/plugins.md#registering-only-modules) for how to move a project over.

### Default auto imports presets

When a project does not set `imports.presets`, `@wolfstar/schema` resolves it to `@wolfstar/http-framework`,
[`@wolfstar/decorators`](https://stars-components.js.org/documentation/packages/decorators), and `@wolfstar/env-utilities`. Auto import generation
skips presets that are not installed in the project. The resolved list is available on
`config.imports.presets`:

```typescript theme={"system"}
import { loadStarsConfig } from '@wolfstar/schema';

const config = await loadStarsConfig({ cwd: process.cwd() });
console.log(config.imports.presets);
```

### Environment and hooks

`StarsConfig` includes `env` and `hooks`. `env` accepts `true`, `false`, or the setup options of
`@wolfstar/env-utilities` (`path`, `env`, `prefix`, `loader`, `debug`, `encoding`) plus `enabled`. `hooks` accepts the
`stars` CLI lifecycle hooks, keyed by full name (`'build:done'`) or nested under their namespace
(`{ build: { done() {} } }`), as a function or an array of functions. `loadStarsConfig` flattens `hooks` to full names
and raises [`UNKNOWN_HOOK`](https://stars-components.js.org/documentation/errors/config#unknown_hook) for a name it does not recognize.

```typescript theme={"system"}
// stars.config.ts
import { defineConfig } from '@wolfstar/schema/config';

export default defineConfig({
	env: { prefix: 'BOT_' },
	hooks: {
		'config:resolved'(config) {
			console.log(`Building ${config.entry}`);
		}
	}
});
```

The hook signatures are exported as types:

```typescript theme={"system"}
import type { StarsHooks, StarsHookName, StarsHooksConfig, StarsEnvConfig } from '@wolfstar/schema';
```

The resolved [`ResolvedEnvConfig`](https://stars-components.js.org/documentation/api/schema/interfaces/ResolvedEnvConfig) keeps `options` exactly as
`stars.config` wrote them, because that is what the bot receives. Its `loader` field holds the loader the bot will use:
`options.loader` when it is set, otherwise `'varlock'` when `@wolfstar/env-utilities` would pick it by itself. From
`future.compatibilityVersion` 6, that is a project with a varlock `.env.schema`, an installed `varlock`, and no
`env.path`. `undefined` leaves the choice between `dotenv` and `node` to the runtime. Read `config.env.loader`, not
`config.env.options.loader`, to know how the variables are loaded. Call
[`detectVarlock(root)`](https://stars-components.js.org/documentation/api/schema/functions/detectVarlock) to inspect a project's schema, installation,
and dependency yourself.

```typescript theme={"system"}
import { detectVarlock, loadStarsConfig } from '@wolfstar/schema';

const config = await loadStarsConfig({ cwd: process.cwd() });
console.log(config.env.loader); // 'varlock' | 'dotenv' | 'node' | undefined

const { schema, installed } = detectVarlock(config.root);
```

See the [framework reference](https://stars-components.js.org/documentation/packages/http-framework.md#environment-env) for what each `env` option and
[hook](https://stars-components.js.org/documentation/packages/http-framework.md#hooks) does.

### Dev options

The `dev` block configures `stars dev`. Besides `banner`, `typecheck`, `tunnel`, and `logFile`, it accepts:

| Option | Type | Default | Description |
| - | - | - | - |
| `dev.layout` | `'auto' \| 'dashboard' \| 'panel'` | `'auto'` | The interactive UI. `'auto'` picks the full-screen dashboard on a terminal of at least 90×20 and the compact panel otherwise. |
| `dev.portConflict` | `'prompt' \| 'next' \| 'error' \| 'continue'` | `'prompt'` | What `stars dev` does when the listener port is occupied: ask, use the next free port, fail, or start anyway. |
| `dev.url` | `string` | inferred from the port | The URL shown in the dev UI and used for `dev.health`. The inferred URL follows the chosen dev port. An explicit URL is for display and health checks only, and `--port` never rewrites it. |
| `dev.logs.channels` | `string[]` | every channel | The log channels shown when `stars dev` starts. Other channels start hidden but can still be toggled. |
| `dev.logs.levels` | `StarsLogLevel[]` | `['error', 'warn', 'info', 'debug']` | The log levels shown when `stars dev` starts. |
| `dev.logs.dir` | `string \| false` | `false` | A directory, relative to `root`, that receives one log file per run (`dev-<timestamp>.log`). |
| `dev.logs.keep` | `number` | `10` | How many per-run files `dev.logs.dir` keeps, the current run included. Must be a positive integer. |
| `dev.commands.refresh` | `'prompt' \| 'auto' \| 'off'` | `'prompt'` | What `stars dev` does when the bot's application commands change: ask before redeploying, redeploy right away, or only report it. |
| `dev.hmr` | `boolean` | `true` | Leaves changes to pieces to the bot's own hot reload instead of restarting it. `false` always restarts. |

```typescript theme={"system"}
// stars.config.ts
import { defineConfig } from '@wolfstar/schema/config';

export default defineConfig({
	dev: {
		layout: 'auto',
		portConflict: 'prompt',
		logs: { channels: ['bot', 'commands', 'interactions'], levels: ['error', 'warn', 'info'], dir: 'logs', keep: 10 },
		commands: { refresh: 'prompt' },
		hmr: true
	}
});
```

The log file always receives every entry, whatever `dev.logs.channels` and `dev.logs.levels` say. `dev.commands.refresh`
and the bot-side log channels need `@wolfstar/http-framework` 6.1 or later. See
[`stars dev`](https://stars-components.js.org/documentation/packages/cli#stars-dev) for how each option behaves.

### TUI options

The top-level `tui` block configures the presentation of `stars dev`:

| Option | Type | Default | Description |
| - | - | - | - |
| `tui.style` | `'nuxt-style' \| 'dashboard' \| 'none'` | unset | `'nuxt-style'` uses the compact panel, `'dashboard'` the full-screen view, and `'none'` plain logs. Unset keeps `dev.layout`'s choice. |

```typescript theme={"system"}
// stars.config.ts
import { defineConfig } from '@wolfstar/schema/config';

export default defineConfig({
	tui: { style: 'nuxt-style' }
});
```

`--style` and `--layout` on the command line take priority over `tui.style`, which takes priority over `dev.layout`. See
[Terminal style](https://stars-components.js.org/documentation/packages/cli.md#terminal-style).

An unknown value for `tui.style`, `dev.layout`, `dev.portConflict`, `dev.logs.levels`, or `dev.commands.refresh` raises the
[`INVALID_CHOICE`](https://stars-components.js.org/documentation/errors/config#invalid_choice) diagnostic. The package also exports `LOG_LEVELS` (every
level, from the most verbose to the most severe) and `DEFAULT_LOG_LEVELS` (the levels shown by default):

```typescript theme={"system"}
import { DEFAULT_LOG_LEVELS, LOG_LEVELS, type StarsLogLevel } from '@wolfstar/schema';
```

## Framework facades

`@wolfstar/http-framework` exposes two facades that forward this package's exports unchanged, matching Nuxt's
package layout:

* `@wolfstar/http-framework/config` — the historical entry point; keep using it in `stars.config.*` files.
* `@wolfstar/http-framework/schema` — the type-focused entry point, mirroring `nuxt/schema`.

Both preserve the same exports and function identities as `@wolfstar/schema`, so existing imports continue to work
without modification.

## Server integration contract

`@wolfstar/schema` exports the `Builder` contract and `BuilderContext` type used by the optional build integrations:

* [`@wolfstar/vite-server`](https://stars-components.js.org/documentation/packages/vite-server) — Vite build and dev server.
* [`@wolfstar/nitro-server`](https://stars-components.js.org/documentation/packages/nitro-server) — Nitro build and dev server.

Both integrations implement the same lifecycle (`watch`, `close`, `start`/`success`/`failure`/`log` events) so
`@wolfstar/cli` can load them on demand behind the existing experimental flags without depending on either package
at install time.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.