# Set up Clearcote

These steps are for a coding agent (Claude Code, Codex, Cursor, Windsurf, Cline, ...) setting up Clearcote for
the user it works with. Clearcote is a Chromium build with fingerprint controls compiled into the engine, plus
SDKs for Python, Node and .NET whose `launch()` returns a normal Playwright browser. The same steps, for people
and in eight languages: https://www.clearcotelabs.com/docs/agents#setup-runbook

Work through the steps in order: installed, licence set, running, verified. Each one ends with a check, and a
step is done only when its check passes. Keep your progress in a file, so that a new session, or a user who
comes back tomorrow, resumes at the first step that is not done instead of starting over.

## Rules

- Run every command yourself and read its output. If a step fails, stop: show the user the step, the command
  and the exact error line, then the fix from "When a step fails" below. Do not work around a failed check (skipping
  verification, pinning an older build, switching builds) without asking.
- Get Clearcote only from its official sources: the `clearcote` package on PyPI, npm or NuGet,
  `clearcote-mcp` on PyPI and npm, the `teamflatearth/clearcote` Docker image, and the releases of
  clearcotelabs/clearcote-browser on GitHub. The SDK downloads the browser itself and checks its SHA-256. Never
  fetch a browser build from anywhere else, and never turn that check off.
- Licence keys and API keys are secrets. Never ask the user to paste a key into this chat, and never print, log
  or commit one. If one is pasted anyway, do not repeat it or write it into a file, and suggest rotating it at
  https://www.clearcotelabs.com/dashboard/licenses.
- When a link has expired or is dead, do not look for a copy. The download links the SDK uses are short-lived
  and it requests a fresh one on every run, so rerun the command rather than reuse a URL. For any other link (a
  sign-in, a device code, a dashboard page, a link the user forwarded), go back to where it came from, or ask
  the user for a new one. Never use a mirror, a cached copy or an unofficial package.
- Install into the user's project (its virtualenv, `package.json` or `.csproj`), not globally, unless the
  user asks otherwise. Ask before you edit config outside the project (an MCP client's config, for example)
  and before you start anything that costs money (hosted browsers are billed per GB).
- Done means the exact browser version is confirmed, not that a package installed.

## Keep a progress file

Write `clearcote-setup.json` in the project root (it holds no secrets) and update it after every check.
`route` is `python`, `node`, `dotnet`, `mcp` or `docker`; `build` is `open` (no key) or `licensed`
(Free with GitHub or Pro); `blocked` records what you are waiting for.

```json
{
  "route": "python",
  "build": "licensed",
  "steps": {
    "installed":   { "done": true,  "checked": "2026-10-06T10:12:00Z", "evidence": "clearcote SDK 0.50.1" },
    "licence_set": { "done": false },
    "running":     { "done": false },
    "verified":    { "done": false, "browser_version": null }
  },
  "blocked": { "step": "licence_set", "waiting_for": "user approves the device sign-in" }
}
```

At the start of a session, read the file and continue from the first step that is not done. Rerun the check of
any earlier step you rely on, because a key can expire and a cache can be cleared between sessions.

## Step 0: choose the route and the build

Ask the user once, and record the answers.

- **The route.** For their own code: the SDK in the project's language, Python 3.8+, Node 20+ or .NET 8 (if
  there is no project yet, suggest Python). For you, the agent, to browse with: the MCP server (Python 3.10+).
  As a CDP endpoint for an existing framework: the Docker image.
- **The build.**
  - **Open build.** No key, no sign-up. Chromium 150, open source (BSD-3). Good enough to start.
  - **Latest build.** Chromium 155, with a licence key: free with GitHub for one browser at a time,
    or Pro for up to 250 browsers at once.

The browser runs on Windows x64 and Linux x64, and the Docker image is x64 too. On macOS or an ARM machine, stop
and say so; hosted browsers (https://www.clearcotelabs.com/docs/hosted-browsers) are the option that needs no local browser.

## Step 1: installed

```bash
pip install -U clearcote                  # Python, inside the project's virtualenv
npm install clearcote                     # Node
dotnet add package Clearcote              # .NET (see below for the checks)
pip install -U clearcote clearcote-mcp    # MCP server: Python 3.10+, no mcp pin needed
docker pull teamflatearth/clearcote       # Docker
```

Check: `clearcote version` (Node: `npx clearcote version`) prints 0.50.1 or newer. For Docker,
`docker image ls teamflatearth/clearcote` lists the image.

.NET has no `clearcote` command of its own. Check that `dotnet list package` lists `Clearcote`, then run
every `clearcote` command in steps 1 to 3 as `npx -y clearcote <command>` (Node 20+) or
`pipx run clearcote <command>` (Python 3.8+). That adds nothing to the project, and the command uses the same
browser cache and licence file (`~/.clearcote/license.key`) as the .NET SDK. If the machine has neither Node nor
Python, ask the user to install one: without the command the browser version cannot be confirmed, so the setup
cannot be verified.

## Step 2: licence set

For the open build, mark this step done with the evidence `open build, no key`. For the latest build, the key
goes to the user's machine without passing through you:

- If `clearcote --help` lists `clearcote login --device`, run `clearcote login --device` (Node:
  `npx clearcote login --device`). It prints a link and a short code. The user opens the link in their own
  browser, signs in and approves (a free key needs a GitHub account at least 30 days old), and the SDK saves
  the key to `~/.clearcote/license.key` without showing it.
- Otherwise the user claims a key at https://www.clearcotelabs.com/dashboard/licenses ("Connect GitHub and get it free", then "Claim
  my free key"; a Pro key is on the same page) and runs `clearcote login` (Node: `npx clearcote login`) in
  their own terminal, pasting the key there: it shows on their screen, never in this chat. Give them those
  steps and wait until they say it is done. They can instead set `CLEARCOTE_LICENSE_KEY` themselves, in
  their shell profile, CI secrets, the `env` block of their MCP client config, or their Docker environment
  (`docker run -e CLEARCOTE_LICENSE_KEY` then passes it in without the value appearing in the command).

Never run `clearcote login <key>` yourself (the key would land in your transcript and the shell history), and
do not open `~/.clearcote/license.key`.

Check: `clearcote info --quick` shows the `Licence` line as a masked key `from file` or `from env`, which
is all you need to see. `none (free build)` means no key was found. A key set only in an MCP client's config
or a container is invisible to your shell; check that the variable name is there without printing its value.

## Step 3: running

```bash
clearcote install    # downloads and verifies the build the key allows
clearcote info       # starts the browser once, headless
```

(Node: `npx clearcote install` and `npx clearcote info`.) Check: `clearcote info` prints
`Launch test     ok (<version>)`; with `--json`, `launch.ok` is `true`, `launch.version` holds the version
and `binary.tag` the build. On a Free key this uses the one browser seat for a moment, so close any other
Clearcote browser first. Then, by route:

- **SDK.** Run a first script. Python, saved as `clearcote_hello.py`:

  ```python
  import clearcote

  browser = clearcote.launch(fingerprint="first-run")
  page = browser.new_page()
  page.goto("https://example.com")
  print(page.title())
  print(page.evaluate("navigator.userAgent"))
  browser.close()
  ```

  Node, saved as `clearcote_hello.mjs`:

  ```js
  import { launch } from "clearcote";

  const browser = await launch({ fingerprint: "first-run" });
  const page = await browser.newPage();
  await page.goto("https://example.com");
  console.log(await page.title());
  console.log(await page.evaluate(() => navigator.userAgent));
  await browser.close();
  ```

  .NET: follow the C# tab of https://www.clearcotelabs.com/docs/playwright. Check: it prints `Example Domain` and a Chrome user
  agent, then exits. The `fingerprint` seed is the identity: the same seed gives the same device every time,
  and a different seed gives an unrelated one. Use one seed per account.
- **MCP server.** Register the command `clearcote-mcp` with the client (ask first; give the full path if it
  is in a virtualenv):
  - Claude Code: `claude mcp add clearcote -- clearcote-mcp`
  - Codex: `codex mcp add clearcote -- clearcote-mcp`
  - Cursor, Windsurf, Cline, Claude Desktop: add
    `{"mcpServers": {"clearcote": {"command": "clearcote-mcp"}}}` to the client's MCP config.

  Restart the client and call the `navigate` tool on `https://example.com`; it returns the final URL and
  the page title. See https://www.clearcotelabs.com/docs/mcp.
- **Docker.**

  ```bash
  docker run -d --name clearcote -p 127.0.0.1:9222:9222 -e CC_FINGERPRINT=setup-check teamflatearth/clearcote
  # the latest build: add  -e CLEARCOTE_LICENSE_KEY -v clearcote-cache:/opt/xdg-cache  before the image name
  docker logs clearcote | grep "engine:"   # [clearcote] engine: <path> (licensed) or (free)
  curl -s 127.0.0.1:9222/json/version      # answers once the browser is up
  ```

## Step 4: verified

Compare what step 3 printed with the build the user should have. In Docker, the build tag is part of the engine
path in the log line.

| Build | Build tag | Launch test version |
| --- | --- | --- |
| Latest build (licence key) | `pro-155.0.8059.39-r42` | `155.0.8059.39` |
| Open build (no key) | `v0.1.0-pre.23` | `150.0.7871.114` |

A Pro plan that pins an older build reports that build instead. If it is not the build the user chose, stop and
tell them. When the version matches, set `verified` to done with the version, and tell the user: the route,
the SDK version, which build runs and its exact browser version, where the first script is and how to run it,
where the key is kept (file or environment variable, never the key itself), and the docs: https://www.clearcotelabs.com/docs (all of
it in one file, for agents: https://www.clearcotelabs.com/llms-full.txt).

## When a step fails

| You see | What to do |
| --- | --- |
| `error: externally-managed-environment` from pip | Install into a virtual environment (`python -m venv .venv`) or with pipx. Do not add `--break-system-packages` without asking. |
| Python older than 3.8 (3.10 for the MCP server), or Node older than 20 | Ask the user to install a supported version. Do not install an older Clearcote to fit. |
| `Clearcote ships Windows x64 and Linux x64 only.` or `Clearcote PRO ships Windows x64 and Linux x64 only.` | Unsupported machine. Stop, as in step 0. |
| `Clearcote archive SHA-256 mismatch — refusing to use it.` | The download was damaged or altered. Run `clearcote install` once more; if it repeats, stop and report. Never skip the check. |
| `Clearcote PRO download not authorized (HTTP 401)` or `(HTTP 403)`, or a `LicenseRevokedError` at launch | The key is wrong, expired or revoked, or the plan is inactive. Free keys last 30 days: the user renews on the Licenses page, then you redo step 2. |
| `ConcurrencyLimitError` (`CONCURRENCY_LIMIT_EXCEEDED`) | Every browser the plan allows is already running. A Free key runs one browser at a time across all machines and containers. Close the other one, then retry once; do not loop. |
| `Could not reach the license server` | The latest build needs outbound HTTPS to www.clearcotelabs.com when it starts. Ask the user about a firewall or proxy; the open build needs no licence server. |
| `clearcote login --device` ends with `Nothing was saved.` | The code expired, or the sign-in was not approved. Run `clearcote login --device` again for a new link and code; never reuse the old link. |
| `Launch test     FAILED` with `missing library:` lines (Linux) | Install the listed system libraries with the user's package manager. That usually needs `sudo`, so ask first. |
| A link returns 403, 404 or 410, or a sign-in link has expired | Rerun the command that produced it, or get a fresh link from where it came from. Never use a mirror. |
| The AI client does not list the Clearcote tools | Restart the client. If `clearcote-mcp` is not on the PATH the client uses, put the full path of the executable in the config, or use `npx -y clearcote-mcp`. |

## Optional, only if the user wants it

- **A proxy.** Pass a Playwright proxy, `proxy={"server": "http://host:port", "username": "...", "password": "..."}`,
  and `geoip=True`, so the timezone and language follow the proxy's exit IP. See https://www.clearcotelabs.com/docs/proxies.
- **A browser for you, the agent, over MCP**, if that was not the route: `pip install -U clearcote-mcp`
  (Python 3.10+), then register it as in step 3. For the latest build the server finds the key saved in
  step 2, or the user adds `CLEARCOTE_LICENSE_KEY` to that server's `env` themselves.
- **No machines to run it on.** Hosted browsers start the same browser on Clearcote's servers with one API
  call. They need an API key from https://www.clearcotelabs.com/dashboard/api-keys and are billed per GB, so ask first. See
  https://www.clearcotelabs.com/docs/hosted-browsers.
