Describe it in the chat on the left. You get a working tool back in seconds, and everything after that is editing — in chat, on the canvas, or in the JSON.
Or start from one that already works — these open running, and you can change anything about them.
This is the whole tool. Edit it here and press Apply to update the preview — it is checked against the CobbleIT contract as you type, so you find out what is wrong before you apply it. See the for what each field means.
How to describe a tool, refine it, and edit the JSON by hand.
The generator does better with concrete nouns than adjectives. Say what goes on the screen, not how it should feel.
| Instead of | Try |
|---|---|
| "a nice fitness app" | "A workout tracker with a counter for each of squats, press-ups and pull-ups, a reset button, and a checkbox list for today's session" |
| "something for work" | "A stocktake tool: an input for the item name, a counter for quantity, a running total, and a Save button that appends the item to a list" |
| "make it good" | "Use one accent colour, group the counters into a single row, and give the whole thing a dark background" |
These are the box types the generator can produce. Ask for them by name and you will get them.
Buttons and inputs trigger actions against other boxes. Ask for behaviour and the generator wires it up.
| Action | What it does |
|---|
Every refinement rebuilds the whole tool with your change applied, so you can keep going in one conversation. Things that work well:
| Command | Effect |
|---|---|
| @3 | Load community tool #3 into the preview, ready to modify |
| … @3 … | Mention a community tool inside a sentence to use it as a starting point, e.g. “make @3 dark and add a notes box” |
| Shift + Enter | New line instead of sending |
The holds the whole tool — there is no other file, and no code behind it. Every box you see is one entry in this document, and changing an entry changes the tool. It is validated as you type, so a mistake shows up before you apply it. The shape is:
| Field | Meaning |
|---|---|
| gridCols / gridRows | Size of the canvas. Cells are square. Default 16 × 256. |
| tabs[].id | A name, up to 64 characters of letters, numbers, hyphen and underscore: today, week, goals. This is what SWITCH_TAB targets. Older tools using a single letter still load. |
| boxes[].id | Unique across the whole document. Actions and formulas refer to boxes by this id. |
| position / size | x,y is the top-left cell; w,h is the span. x + w must not exceed gridCols, and boxes must not overlap. |
| config | Depends on the box type — a TEXT box takes value, a BUTTON takes text, a COUNTER takes a numeric value. |
| actions[] | event is ON_CLICK or ON_TEXT_CHANGE; targetBoxId must name a box that exists (or a tab id, for SWITCH_TAB). |
| boxes[].compute | { "formula": "SUM({log.kg})" } — the box shows the result and recalculates it whenever anything it reads changes, on any tab. |
| boxes[].shared | Mirror this box to everyone in the same room. Needs sharing.enabled on the document. |
| state | { "persist": "local" } keeps entries and ticks in this browser between visits. Add "lock": true to put the tool behind a passcode and encrypt what it stores. |
| sharing | { "enabled": true, "label": "Route board" } turns on the room bar above the tool. |
| requestBlocks[] | Named HTTP requests for live data, each able to carry a credential. See Integrations. |
A box can carry a compute formula instead of a fixed value. The formula reads other boxes
by id — {weight}, {log.kg} — and the tool recalculates it every time anything
it reads changes. That includes boxes on other tabs, which is what makes a multi-tab tool behave
like one thing: log a set on the first tab and the totals on the third are already right when you get there.
This is a fixed expression grammar, not a scripting language. There is no way to write a loop, read a property, or name a web address in a formula, so a tool someone else published can compute a wrong number and nothing worse.
| Write this | And you get |
|---|---|
{kg} * {reps} | Arithmetic over two boxes. + - * / % and brackets. |
SUM({log.volume}) | The total of one column of an entry log, table or list. |
AVG · MIN · MAX · COUNT | The rest of the column arithmetic. COUNT({log}) counts rows. |
DONE({tasks}) · TODO({tasks}) | How many are ticked, and how many are not. |
ROUND(x, 2) · FLOOR · CEIL · ABS · SQRT · POW · CLAMP | Number shaping. |
IF({a} > {b}, 'over', 'under') | A readout in words. AND, OR, NOT and == != < > <= >= all work. |
CONCAT('€', ROUND({total}, 2)) | A sentence built from live values. LEN and WORDS measure text. |
TODAY() · NOW() · DAYS_BETWEEN(a, b) | Dates. |
Select the box in the Simulator’s edit mode and there is a Formula field in the properties panel; it tells you straight away if you name a box that is not there.
Add "state": { "persist": "local" } to the document and everything the person using the
tool changes — ticks, entries, notes, slider positions — is still there next time they open it. It is
kept in their own browser; nothing is uploaded, and it never reaches us.
Add "lock": true alongside it and the tool asks for a passcode before it will show anything,
and encrypts what it stores with a key derived from that passcode (AES-GCM, PBKDF2). The passcode is
never stored and never sent, which also means nobody can reset it — lose it and the
entries are gone. That is the honest trade for a diary that is actually private.
Set "sharing": { "enabled": true, "label": "Route board" } on the document and
"shared": true on the boxes that everyone should see the same way. A bar appears above the
tool: press New room to get a code, or type one someone gave you. Everyone signed in and
on that code sees the same values in those boxes, live, and can see who else is on the board.
keyField set to the person's name — then answering twice replaces your row
instead of adding another.A tool can pull from a real API. Connect the service on the first, then ask for it by name — “show the Bitcoin price from CoinGecko”. Your credentials stay in this browser: they are never sent to the generator and are stripped from anything you download or publish.
There are two paths, and the difference matters. A box dataSource with a URL fetches one
public endpoint with no key attached. A requestBlock is a named request that can
carry a credential — that is what a tool needs for GitHub, Todoist or anything behind a token. When you
open a tool whose requests need a key you do not have, a Keys needed strip appears above
it; what you type there is saved in this browser against that tool and nowhere else.
Google is different, and better. A tool that reads your Google Analytics, Search Console or Sheets data shows a Connect button instead of a key box. The sign-in happens directly between your browser and Google, which hands the page a token — there is no secret to paste and nothing to store. That token lives in memory until you close the tab: it is in nothing you download, nothing you publish, and it never reaches us. Google shows you exactly what a tool is asking to read before you agree, and you can withdraw it from your Google account at any time. Other OAuth services (Spotify, Google Calendar) are not wired up here yet and work in the Android app; the tool says so rather than failing silently.
Both paths are limited to the same thing: a service that lets a web page read its answers. Plenty do not — Notion and most self-hosted admin APIs among them — and no amount of configuration changes that from inside a browser. The marks each service accordingly rather than letting you find out by connecting one.
A Google Sheet published with File → Share → Publish to web → Comma-separated values
serves its contents from docs.google.com to any page that asks — no key, no sign-in,
nothing in between. That makes it the way in for every source that will not answer a browser
directly: get the numbers into a sheet, by hand, by formula, by
IMPORTDATA, or by a script that calls the API on a timer, and a tool can read them.
Point a box at the published URL with "type": "csv", a rowIndex and a
column, both counting from zero and both skipping blank lines. Quoted cells, embedded
commas and line breaks inside a field are all read properly, which matters because every analytics
export uses them. A value that arrives this way is an ordinary number: formulas elsewhere in the
tool can divide it, total it and compare it exactly as if you had typed it.
The Marketing board from a Google Sheet template in
is a worked version, with the sheet layout it expects.
A tool is one JSON document, and it opens either here or in the Android app. The two are not at parity, and pretending otherwise would mean a tool that quietly does nothing on the other side. Downloading a tool tells you which of its features are web-only.
| Runtime | Where it stands |
|---|
You do not need one. Describing, generating, refining, the Simulator, the JSON tab and downloading all work signed out. An account adds three things:
Sign-in is a link emailed to you — no password. Your email address is never shown publicly: published tools carry the display name you set in , or “anonymous” if you leave it empty.
Every one of these is a finished tool, not a screenshot. Click it and it opens running in the Simulator — press the buttons, tick the boxes, watch the totals on the other tabs move. Then make it yours: change it in chat, drag it about on the canvas, or edit the JSON directly. Nothing needs an account except the shared ones.
Tools saved to your account. They follow you between devices, unlike the copy this browser keeps.
Every AI-generated tool is saved here automatically. Type @3 in chat to load community #3, or click a card to open it in the Simulator.
Connect a service once, then ask for it by name in chat — “show my open GitHub issues”, “add the Bitcoin price”.
Click a service to connect it. Tools may only call these hosts — the generator will not invent an endpoint, and a tool that tries to reach anywhere else is rejected before it reaches you.
Enter the passcode to unlock it.
The passcode never leaves this browser. It encrypts what this tool stores here and is not recoverable — nobody can reset it for you.