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

> ## Agent Instructions
> Reticle is a dev-only, localhost-only verification layer for AI coding agents. It reads program truth (network, state, console, routing, animations, framework state) from inside a running web app and returns a deterministic verdict with evidence. It is not a screenshot tool and not a browser automation library.
> Only `reticle_act_and_wait` and `reticle_assert` produce a verdict. Every other tool moves or reads the app and proves nothing. A drive that ends without one of those two has no result, however many tools it used.
> A verdict of `verified: "unknown"` is not a pass. It means Reticle drove the app and could not tell what happened. Report it as unknown; never weaken a check to make it pass.
> Package names are scoped `@reticlehq/*` and the CLI is `reticle`. Install with `npx reticle init`. The complete tool surface is on the `/usage` page; `/agent-cheatsheet` is the one-screen version.

# @reticlehq/babel-plugin

> A Babel plugin that stamps data-reticle-source on JSX host elements so Reticle can name the file a node came from.

`@reticlehq/babel-plugin` puts the source location back. React 19 dropped `_debugSource`, which is what source mapping used to rely on, so without this the tools can tell you the component name but not the file.

**Version 2.8.0. Apache 2.0. CommonJS. No runtime dependencies. Peer dependency: `@babel/core ^7`.**

## What it stamps

```jsx theme={"dark"}
<button onClick={submit}>Sign in</button>
```

becomes, in dev only:

```jsx theme={"dark"}
<button onClick={submit} data-reticle-source="src/components/Login.tsx:81:6">
  Sign in
</button>
```

The path is relative to `process.cwd()`, with backslashes normalized to forward slashes. A file with no name stamps `unknown`.

## What it skips

* Component tags. Only lowercase host elements are stamped, because a component's own JSX gets stamped where it is defined.
* Elements that already carry the attribute.
* Nodes with no location information.
* Anything whose tag name is not a plain `JSXIdentifier`.

## Do you install it?

Only if you are wiring Babel yourself. [`@reticlehq/vite-plugin`](/packages/vite-plugin) and [`@reticlehq/next`](/packages/next) both pull it in.

```bash theme={"dark"}
npm i -D @reticlehq/babel-plugin
```

## The export

One export, via `export =`. There are no named exports and no `default` interop wrapper, because Babel `require()`s the module and takes the object directly.

```ts theme={"dark"}
function reticleSourcePlugin({ types }: { types: typeof BabelTypes }): PluginObj<PluginPass>;
```

The Babel plugin name is `reticle-source`. Its visitor handles `JSXOpeningElement` only.

**It takes no options.** The plugin reads nothing from `state.opts`.

## Wiring it by hand

```js theme={"dark"}
// babel.config.cjs
module.exports = {
  plugins: process.env.NODE_ENV === 'development' ? [require('@reticlehq/babel-plugin')] : [],
};
```

<Warning>
  Do not write `require('@reticlehq/babel-plugin').default`. With `export =` there is no `.default`,
  and an old README example got this wrong.
</Warning>

## Why an attribute rather than a runtime lookup

The stamp survives minification of everything else, costs nothing at runtime, and is readable from the DOM node itself. That is what lets [`reticle_inspect`](/tools-inspect) answer with a file and a line rather than a component name and a shrug.
