CoworkkitDocs
Sign inCreate account
© 2026 CoworkkitTerms of ServiceRefund PolicyData Processing AddendumPrivacy PolicyCookie PolicyData & Security

Start here

  • Getting started
  • The setup prompt
  • How it works

Declaring your app

  • Actions, surfaces & elements
  • Hand mode
  • Control & confirmation
  • Show while it talks
  • 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
  • Browser storage
  • Troubleshooting & FAQ
  • Error codes
All docs

Docs

Show while it talks

Label the things on your page and the co-worker lights, circles, brings up and puts away what it talks about, timed to its words.

Your co-worker can show what it is talking about. When it says a customer’s name, that row lights up. It can circle the answer, bring a chart onto the page when it says “here’s the revenue chart”, put it away when it moves on, and make a roadmap’s milestones appear one by one as it names them. Every move is timed to the spoken word.

None of this needs permission. A move only changes what is shown; it never clicks, types, or changes anything in your app. Anything with consequences stays an action.

Showing is in early access and off until we switch it on for your workspace, so ask us to enable it. While it is off the co-worker makes no moves, and nothing is sent; your page’s own useStage controls still work.

Label the things

Put data-coworkkit-item on each thing the co-worker might talk about, set to the name it would say. That is the whole change for lighting and marking.

tsx
<table data-coworkkit-element="orders">
  {orders.map((o) => (
    <tr key={o.id} data-coworkkit-item={o.customer}>
      …
    </tr>
  ))}
</table>
  • The label is a spoken name, not an ID. Use what people say: "Acme Europe", not "cust_8f2". We match it to the co-worker’s words, ignoring case and accents, and the longest name wins ( “Acme Europe” beats “Acme”).
  • data-coworkkit-element is optional. Put it once on the component’s container, with the same name you gave useElement. It tells us which table a row belongs to, so when the conversation is about invoices, the Acme in the invoices table lights up and not the Acme in orders.
  • Two things with the same name both light. They really are both Acme’s. In development the console warns you once.

The four moves

MoveWhat it doesWhat you declare
lightPoints at the thing being talked about right now. It moves with every mention, one thing at a time.Nothing: a label is enough.
markCircles a thing so it stays visible after the voice moves on: the answer, a warning, a recommendation.Nothing: a label is enough.
showBrings a panel onto the page when the co-worker says it is showing it. On a list's items: they appear one by one as they are named.moves: ["show"] on the element, or itemMoves: ["show"] for its items.
hidePuts a panel away when the co-worker moves on.moves: ["hide"] on the element.

One effect at a time: a thing never shows the glow and the circle together. A circle on the lit thing is drawn when the light moves on.

Bring panels up and put them away

Declare the bigger moves on the element. The co-worker brings the panel up when it says it is showing it (“here’s the revenue chart”), never on a passing mention or a question, and puts it away when it moves on (“back to your orders”).

tsx
useElement({
  name: "chart",
  state: { quarters },
  moves: ["show", "hide"],
});

// Render it by the stage state...
const chart = useStage("chart");
return chart.shown ? <RevenueChart /> : null;
  • Where it starts. An element that can be shown starts hidden; one that can only be hidden starts shown. Set shown on useElement to choose. The start applies with or without a session.
  • Your own buttons. useStage("chart").show() and .hide() drive the same state, so a “Show chart” button and the co-worker never disagree. The co-worker never hides a panel your page showed.
  • No code at all. If the panel’s container carries data-coworkkit-element, we set data-coworkkit-shown on it and hide it while it is "false". Our rule has zero specificity, so your own CSS always wins.

Walkthroughs

Add "show" to itemMoves and the element’s items appear one at a time as the co-worker names them. A declared itemMoves list replaces the default (["light", "mark"]), so list every move you want. When it moves on, or goes quiet for two seconds, the rest appear.

tsx
useElement({
  name: "roadmap",
  state: { milestones },
  moves: ["show", "hide"],
  itemMoves: ["show", "light"], // replaces the default (light and mark)
});

Custom looks

The glow and the circle are drawn on our own layer, on top of your page, so your components don’t change. For a look of your own, such as a bar on a canvas chart, read the stage:

ts
const { shown, lit, marked, waiting } = useStage("chart");
// lit: the name being talked about, or null
// marked: the circled names · waiting: walkthrough items not reached yet

CSS-only pages can style the attributes we set on labelled nodes: data-coworkkit-lit, data-coworkkit-marked and data-coworkkit-shown. The intensity prop on CoworkkitProvider applies too: "off" draws no glow or circle, and the stage state still updates.

When the AI writes back

When typing and written replies are on for your workspace (also in early access), a written reply has no voice to time the moves to. So they land with the reply, already in their final state: panels shown or put away, the answer circled, and the first thing it named lit for a moment. In the reply itself, every word that names a thing becomes pointable: point at it and that thing lights up. In voice, the moves follow the voice; in text, they follow the reader.

What we read

Only your labels and where the labelled things sit on the screen. We never read text, input values, or anything you didn’t label. The names go to our servers so the co-worker can match them; descriptions come from the state you already declare with useElement.

Troubleshooting

  • Nothing lights. Showing may not be on for your workspace yet. Otherwise, check that the label is the name the co-worker says, and that the thing is on screen: we never scroll your page for a light.
  • A panel never appears. An element with moves: ["show"] starts hidden. The co-worker shows it when it says it is showing it; your own controls can call useStage(name).show().
  • The wrong Acme lights. Add data-coworkkit-element to each table so we know which one a row belongs to.
PreviousControl & confirmationNextPatterns & best practices

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