# Development mode

> In a dev build the SDK renders a thin onboarding banner over your app and the co-worker knows it's a dev session — off by construction in production.

In a **development build**, the SDK does three things it never does in production: it renders a thin **onboarding banner** over your app, it **warns** about the two mistakes that otherwise fail silently, and it tells the co-worker it is a **dev session** so it can help you build. Ship a production build and all three vanish — there is nothing to turn off, because a production bundle turns them off by construction.

## Mode comes from the build, not a toggle

Dev mode is on whenever `process.env.NODE_ENV !== "production"` — the same signal your bundler already strips from the browser. It is deliberately *not* a per-coworker setting in the portal: a coworker is shared by every end-user of your deployed app, so a toggle there would show dev behaviour to your users. Mode is a property of the build, full stop. That also means a production bundle contains **zero** dev-banner bytes — the banner module is reached only from a dev-only branch, so your bundler tree-shakes it out.

## The banner

The Provider renders it automatically — you mount nothing. It is a fixed strip across the top of the viewport (it never pushes your layout) with the five steps of the golden path — **key · installed · connected · first action · go live**. Each step is a button that opens a small popover: a live status line, one primary action, and one help link. While a session is live the *installed* step shows the integration-health readout (`connected · N actions · N elements · surface: …`) — the same line the SDK logs once to your console on connect. If a connect fails, the *connected* step shows the raw `reason` and `status` plus a link to the matching [error-codes](/docs/error-codes) entry. Once the co-worker has acted the strip collapses to a small pill; dismissing it is remembered for that origin.

## Hide it — without losing the rest

Two props, both on `<CoworkkitProvider>`. `devBanner={false}` hides only the strip while keeping the console readouts, the guards, and the agent's dev behaviour. `dev` overrides the whole mode: force it on for a staging build that ships as `production`, or off entirely.

**`app/providers.tsx`**

```tsx
"use client";

import { CoworkkitProvider } from "@coworkkit/react";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <CoworkkitProvider
      getToken={getToken} // your token route — see Getting started
      devBanner={false} // hide only the strip; keep the readouts + guards
      // dev={true}      // force dev mode on in a staging build that ships as production
    >
      {children}
    </CoworkkitProvider>
  );
}
```

## The two guards

The hook warning is a silent no-op in production and speaks only in a dev build; the mintSession guard warns in production and throws in a dev build:

- **A hook outside the Provider.** A `useAction` / `useElement` / `useSurface` mounted with no `<CoworkkitProvider>` ancestor registers nothing — so the co-worker “just talks and does nothing.” In dev the SDK warns once, naming the hook and the fix.
- **A secret key in the browser.** Your tenant key is server-side only. If it rides a browser-exposed prefix (`NEXT_PUBLIC_` / `VITE_` / `PUBLIC_`), the server-side `mintSession` guard throws in development and warns in production (never refusing a live mint). It never prints the key.

## The co-worker in a dev session

When it’s a dev session, the co-worker knows it is talking to the developer, not an end-user. On the very first session it opens with one warm line naming its two roles — your build companion in here, and your app’s co-worker for your users. If nothing is declared yet, its first words say so and point you at the sample action (“paste the sample action from the quickstart and say *celebrate*”). And when you ask for something you haven’t wired, it names the missing declaration for that request in one sentence — it never tutors the SDK and never claims it can edit code (that’s your [coding agent](/docs/coding-agent)). In production, with an empty catalogue, it stays a plain talk-only co-worker and never announces its own incompleteness.

This layer is ours to gate: a fleet switch on our side turns the agent’s dev behaviour on or off across the fleet without a redeploy. The banner and the guards are entirely client-side — they follow your build, not our switch.

## Staging from your server

A staging deployment is usually a real `production` build. Besides the `dev` prop, you can force dev mode from your token route by passing `session: { dev: true }` to `mintSession` — it rides the mint opaquely and is never echoed back. Leave it unset for real production.
