CoworkkitDocs
Sign inCreate account
© 2026 CoworkkitTerms of ServiceRefund & Cancellation PolicyPrivacy PolicyCookie PolicyData & Security

Start here

  • Getting started
  • The setup prompt
  • How it works

Declaring your app

  • Actions, surfaces & elements
  • Hand mode
  • Control & confirmation
  • Patterns & best practices

Integrate

  • Backends
  • Usage, quotas & webhooks
  • Multiple coworkers
  • Connect your coding agent

Polish & operate

  • Appearance
  • Languages
  • The Watch panel
  • Development mode

Reference

  • Advanced
  • Configuration
  • Browser & framework support
  • Network requirements
  • Regions
  • Troubleshooting & FAQ
  • Error codes
All docs

Docs

The Watch panel

See what the agent sees and did (live turns, the action timeline, latency): an in-app devtool you drop in during a build.

CoworkkitWatch is a drop-in developer panel you mount during a build to see what the agent perceives and did. It reads the same internal session state the on-screen button does (no new wire, no instrumentation on your side) and renders it as a floating, resizable panel over your app. Because it reads the Provider's context, mount it anywhere inside CoworkkitProvider; where it sits in the tree doesn't matter.

It's the fastest way to answer the two questions every integration raises: does the agent actually see the surfaces and elements I declared, and did my actions fire, and gate, the way I intended?

Drop it in

It ships as a deep import so it stays tree-shakeable: the panel and its code never reach a bundle that doesn't import it. Add one line to the Provider you already have:

app/providers.tsx
"use client";

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

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <CoworkkitProvider
      getToken={async (ctx) => {
        const res = await fetch("/api/session", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify(ctx ?? {}),
        });
        if (!res.ok) {
          // Check before parsing, and guard the parse: an error page (a proxy 404,
          // a framework 500) is often HTML, and a throw here would lose both fields.
          const body = await res.json().catch(() => ({}));
          // Pass the reason AND the status through. That is what lets the button say
          // "Setup needed" for a bad key instead of a generic "Can't connect":
          throw Object.assign(new Error(body.error ?? "session mint failed"), {
            reason: body.reason,
            status: res.status,
          });
        }
        return res.json();
      }}
    >
      {children}
      {/* Mounts only in development; ships nothing to a production build. */}
      <CoworkkitWatch />
    </CoworkkitProvider>
  );
}

Watch renders only in development, and it doesn't open on its own; it's a panel you toggle. Open it from the watch icon in the on-screen button's control row, or press ctrl+shift+k. If you've mounted it and don't see the watch icon, you're almost certainly on a production build, where Watch hides itself by default. That's expected, not a missing feature; It's a dev surface (below) shows how to force it on when you need it.

Props

All optional. Mount it bare and these defaults apply:

tsx
defaultOpen?: boolean;        // default false (closed); true starts it opened
position?: "bottom-left" | "bottom-right" | "top-left" | "top-right"; // default "bottom-left"
hotkey?: string;              // default "ctrl+shift+k"
initialTab?: "timeline" | "catalogue" | "transcript" | "metrics"; // default "timeline" ("state" is accepted and resolves to it: the State strip is always pinned)
maxEntries?: number;          // default 1000: cap on entries shown and exported
redact?: RedactProfile;       // masking policy for transcripts and tool I/O
visibleTo?: () => boolean;    // predicate over your own auth; false mounts nothing
enableInProduction?: boolean; // default false: the QA escape hatch

What it shows

A pinned State strip across the top (session phase, mic, Hand-mode arm state, the active surface, session duration and idle time), plus four tabs:

  • Timeline: the live event stream, turn by turn. Each action call, how it was gated (allowed, Hand-blocked, or held for a confirmation), and its outcome. This is where you watch an action actually fire, or catch the needs_hand_mode that explains why it didn't.
  • Catalogue: the live declared-exposure snapshot. The current surface, every mounted element (including see-only ones), and the full action catalogue with each entry's kind and control. This is what proves the agent sees what you declared. It also marks the declared-vs-live distinction, so a snapshot taken before the agent joins isn't mistaken for "the agent already knows".
  • Transcript: the conversation, both sides, as the agent heard and spoke it.
  • Metrics: per-turn latency, a turn table, and a session summary, for spotting a slow leg without reaching for a profiler.

It's a dev surface

Watch is gated to NODE_ENV === "development" by default. In a production build it mounts nothing, so leaving <CoworkkitWatch /> in your tree is safe. Two escapes exist for when you need it past dev: enableInProduction for a QA build, and visibleTo, a predicate over your own auth that must return true before anything renders (pair it with the redact policy to mask transcripts and tool I/O).

The header's copy and download buttons emit the whole session (state, timeline, transcript, metrics) as a single JSON blob. That's how you hand a teammate the exact observable state you're looking at: send them the export instead of narrating what you saw.

PreviousLanguagesNextDevelopment mode

Machine-readable: this page as Markdown · all docs (llms.txt) · everything in one file (llms-full.txt)