---
title: "Configuration"
description: "The tsconfig options Hem reads, the strictness it overlays, the Vite plugin options, and the generated-file manifest."
image: "https://hem.run/social/hem.png"
---

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

# Configuration

Hem has no configuration file of its own. The nearest `tsconfig.json` is the project file for the CLI, the compiler, the language server, and the Vite plugin.

Project discovery uses TypeScript's own config resolution, so `extends`, `files`, `include`, `exclude`, and all standard `compilerOptions` behave as they do for `tsc`. Hem adds `.hem` as a recognized project extension.

## The `hem` key

```json
{
  "hem": { "effectImportSource": "effect" }
}
```

| Option | Type | Default | Meaning |
| --- | --- | --- | --- |
| `hem.effectImportSource` | Non-empty string | Omitted | Enables the Effect extension and names the module Hem probes and emits imports from |

With the option omitted, the Effect extension is inactive and emitted output contains no Effect imports.

The supported preview sets this option to `"effect"` and uses
exactly `effect@4.0.0`. Accepting a module name here is not a support
guarantee. See [Effect setup](/guides/enable-effect) for the installation and
version contract.

A `hem` value that is not an object, or an `effectImportSource` that is empty or not a string, makes the project configuration invalid.

## What Hem reads from `compilerOptions`

Module resolution, libraries, JSX, paths, target, and project membership all come from the TypeScript configuration. Two of them have Hem-visible consequences.

Project membership comes from `files` and `include`. A `.hem` file outside that coverage is refused rather than checked.

JSX configuration is TypeScript's. `"jsx": "react-jsx"` works against `@types/react` 19 as written. `"jsx": "preserve"` requires `"jsxImportSource": "react"` alongside it; bare `"preserve"` fails with TypeScript's own TS7026, not a Hem diagnostic.

## The strictness overlay

Hem's private no-emit checker forces a fixed set of options regardless of what the project configures:

- `strict`
- `strictNullChecks`
- `noUncheckedIndexedAccess`
- `noEmit`
- `allowImportingTsExtensions`

The overlay applies only inside that checker. An existing application build does not have to adopt these options, and Hem code still receives its guarantees. `noUncheckedIndexedAccess` is what makes `xs[i]` a `?T`.

## Vite plugin options

```ts title="vite.config.ts"
import { defineConfig } from "vite";
import { hem } from "@hem-lang/vite-plugin";

export default defineConfig({
  plugins: [hem({ effectImportSource: "effect" })],
});
```

| Option | Type | Default | Meaning |
| --- | --- | --- | --- |
| `effectImportSource` | `string` | Reads `hem.effectImportSource` from tsconfig | Vite-scoped override of the Effect transport |
| `root` | `string` | Vite's resolved `config.root` | Starting directory for tsconfig discovery |

Before Vite resolves its configuration, the provisional root is the process working directory.

The plugin compiles each `.hem` file to a `.ts` or `.tsx` sibling on disk and resolves `.hem` imports to those siblings. It owns no JSX transform and has no JSX option: Vite and the framework keep that responsibility.

## Formatter options

`@hem-lang/format` accepts `printWidth`, defaulting to 100. This is an API-level option. No tsconfig key and no CLI flag exposes it.

## The generated-file manifest

`.hem/generated-files.json` is written and maintained by Hem, not authored. It carries a fixed schema version, the generator name, ownership policy values, and one entry per source and sibling pair.

The manifest is deterministic and intended to be committed. `hem generated verify` checks it, `hem generated activate` canonicalizes it, and `hem generated exclusions` prints its siblings for other tools' configuration.

## File extensions and output

A `.hem` file emits `.tsx` when it contains JSX and `.ts` otherwise. Relative specifiers ending in `.hem` rewrite to `.ts` at emit.

A `foo.hem` sitting beside a handwritten `foo.ts` is a build error (HEM3002).

Every emitted file is a module. A source file with no imports or exports still emits a trailing `export {}`, so its top-level bindings never join the ambient global scope.

## Normative source

Specification 0.2, §1 (compilation model), §11 (JSX), §13 (modules and interop), §14.1 (extension activation).

Source: https://hem.run/reference/configuration/index.mdx
