# Checkend docs (all pages) > Open-source error tracking for coding agents. Checkend runs as one Cloudflare Worker with a D1 database in your own Cloudflare account, as one Node process with one SQLite file (for example in Docker), or as a hosted install. It is Sentry SDK compatible, and coding agents read its issues through an MCP server. # Checkend guides Source: https://checkend.com/docs/ (Markdown: https://checkend.com/docs/index.md) > Checkend is open-source error tracking for coding agents. It runs as one Cloudflare Worker with a D1 database in your own Cloudflare account, as one Node process with one SQLite file (for example in Docker), or as a hosted install. **Figure: How Checkend works.** Your app, with any Sentry SDK, sends an error event (POST envelope) to the Checkend Worker. The Worker checks the request and answers 200 with the event ID at once. After the response, it writes the issue and the event to the D1 database in one atomic batch. You, or your coding agent, read the issues through the MCP server (/mcp) or the JSON API (GET /v1/issues). ```mermaid flowchart LR App["Your app (Sentry SDK)"] -- "POST envelope" --> W["Checkend Worker"] W -- "200 {id}" --> App W -- "batch write, after the response" --> D1[("D1: issues, events")] You["You or your coding agent"] -- "/mcp or GET /v1/issues" --> W W -- "JSON" --> You ``` > **Status: early development.** Checkend can receive errors from Sentry SDKs, group them into > issues, give them to coding agents through an MCP server and a JSON API, and send alerts. It > has a small web UI for people. Expect changes. ## Guides | Guide | Read it when you want to | |---|---| | [Quick start](https://checkend.com/docs/quick-start.md) | Run Checkend, connect an app, and read its errors. | | [Web UI](https://checkend.com/docs/web-ui.md) | Sign in with a passkey, connect your apps, and read the errors in a browser. | | [Set up with an agent](https://checkend.com/docs/agent-setup.md) | Let a coding agent add Checkend to your apps, with a short-lived setup key. | | [The ce CLI](https://checkend.com/docs/cli.md) | Install and update `ce`, log in, and keep tokens in the keychain. | | [MCP server](https://checkend.com/docs/mcp.md) | Connect a coding agent, and read issue briefs. | | [Webhooks](https://checkend.com/docs/webhooks.md) | Call your agent runner when an issue is new, regressed or verified, or [start an agent from GitHub Actions](https://checkend.com/docs/webhooks.md#start-an-agent-from-github-actions). | | [Alerts](https://checkend.com/docs/alerts.md) | Tell people in Slack, Discord, a GitHub issue or email. | | [AI triage and similar issues](https://checkend.com/docs/ai-triage.md) | Optional model advice on each issue: cause, severity, noise, and similar issues. | | [Verify fixes](https://checkend.com/docs/fix-loop.md) | Link a fix, report deploys, and let Checkend verify the fix in production. | | [Send errors](https://checkend.com/docs/sending-errors.md) | Know what the ingest endpoints accept, and what they return. | | [Source maps](https://checkend.com/docs/source-maps.md) | Upload source maps, so that briefs show the original JavaScript. | | [What Checkend stores](https://checkend.com/docs/what-checkend-stores.md) | Know how events are cleaned, limited and grouped into issues. | | [API](https://checkend.com/docs/api.md) | Read projects, issues and events with HTTP and JSON. | | [Settings and health](https://checkend.com/docs/settings.md) | Change limits, use the Workers Free plan, and check `/health`. | | [Run without Cloudflare](https://checkend.com/docs/self-host.md) | Run Checkend in Docker or on Node, with one SQLite file. | | [Backup and upgrade](https://checkend.com/docs/operations.md) | Back up the database, and upgrade safely. | | [Architecture](https://checkend.com/docs/architecture.md) | Understand how the code is built, and how it can run off Cloudflare. | Open specs: the [Agent Issue Brief](https://github.com/Checkend/checkend/blob/main/spec/agent-issue-brief.md) and the [fix verification protocol](https://github.com/Checkend/checkend/blob/main/spec/fix-verification.md) are written so that other tools can use them too (see [`spec/`](https://github.com/Checkend/checkend/blob/main/spec/README.md)). Contributors and coding agents: read [AGENTS.md](https://github.com/Checkend/checkend/blob/main/AGENTS.md) and [CONTRIBUTING.md](https://github.com/Checkend/checkend/blob/main/CONTRIBUTING.md) first. ## What works today - **Error ingest** with the Sentry protocol. Any Sentry SDK works: change the DSN. Without a Sentry SDK, send JSON to `POST /v1/ingest`. - **Secret removal** before anything is stored. - **Trust levels and allowed origins**: a project that gets events from a browser, a mobile app or an unknown SDK in the last 30 days is low trust, because its DSN is public. A project can allow browser events only from its own websites. - **Grouping** of events into issues. A deploy that only moves code does not create new issues: line numbers and bundle hashes are not used. - **Protection** for your Cloudflare account: size limits, rate limits, caps per project, and a budget mode for the Workers Free plan. - **An MCP server** for coding agents, with issue briefs that mark app data as untrusted. - **Issue actions**: resolve, ignore, unresolve, merge and split, with optional approvals. A resolved issue that gets a new event becomes unresolved again. - **The fix loop**: an agent links its fix, CI reports deploys, and Checkend verifies the fix when the error stops, or marks the issue regressed when the error comes back. - **Alerts** in Slack, Discord, GitHub issues and email, also for spikes, with safe messages. - **Your own scrub rules**: key names and patterns for each project. - **Outgoing webhooks**: signed requests with the issue brief, with retries, for new, regressed and verified issues. - **Unusual tags**: the brief shows tag values that are much more common in an issue than in the project, for example one browser. - **Suspect commits**: the brief can name a commit of the first release that changed a file in the stack trace (a hint, not proof). - **Source maps**: upload them in CI, and the brief shows the original file and lines of minified JavaScript. - **Self-hosting without Cloudflare**: one Docker container (or Node process) with one SQLite file, with backups. - **Agent setup**: a coding agent registers your apps, adds the SDK and connects itself, with a setup key that lasts 1 hour. - **AI triage and similar issues** (optional, off by default): model advice on each issue, in the brief. - **Project delete and DSN rotation**. - **Priority**: each issue has a priority score from the users affected, the events in the last 24 hours, and how recent and how new the issue is. MCP lists the top priority first. - **Triage history**: each decision on an issue (resolve, ignore, merge, split, ...) and each correction of it, for example a resolved issue that comes back. - **Claims and notes**: an agent claims an issue, so that other agents do not work on it, and writes notes to the timeline of the issue. - **A JSON API** (`/v1`) with scoped tokens, and an audit timeline of token and project changes. - **A project CLI** (`npm run project`) to create projects and print their DSNs. - **The `ce` CLI** for people, scripts and agents: issues, setup, MCP, deploys and source maps (see [The ce CLI](https://checkend.com/docs/cli.md)). - **A web UI** with passkey sign-in: connect apps with a prompt for your coding agent, and read the issues and events. ## Not built yet These features are planned. They are **not** available now: - more members, API tokens and releases in the web UI --- # Quick start Source: https://checkend.com/docs/quick-start (Markdown: https://checkend.com/docs/quick-start.md) > This guide shows how to run Checkend, connect an app with a Sentry SDK, and read the errors. You need: - Node 22.18 or later - a clone of the [Checkend repository](https://github.com/Checkend/checkend), with `npm ci` done - for a deploy: a Cloudflare account and `npx wrangler login` ## 1. Run Checkend on your computer 1. Create the local database tables: ```sh npx wrangler d1 migrations apply DB --local ``` 2. Make an admin token, and put it in `.dev.vars` (this file is git-ignored): ```sh echo "ADMIN_TOKEN=$(openssl rand -hex 32)" > .dev.vars ``` 3. Start the Worker: ```sh npm run dev ``` 4. Check that it runs: ```sh curl http://localhost:8787/health ``` The response has `"status": "ok"`. See [Settings and health](https://checkend.com/docs/settings.md#health) for the other fields. ## 2. Or deploy it to your Cloudflare account To run Checkend without Cloudflare, in Docker, on Node, or on a server over SSH, see [Run without Cloudflare](https://checkend.com/docs/self-host.md). The first path is `ce server install cloudflare` (see [the ce CLI](https://checkend.com/docs/cli.md#install-and-manage-a-server)). It makes the Worker and the D1 database on your account, with a Cloudflare API token. It installs only a signed [server release](https://checkend.com/docs/operations.md#server-releases), shows the plan and asks first, and ends with the setup link of the web UI: ```sh ce server install cloudflare ``` Or do the steps below by hand. > **Caution:** a deploy uses resources in your Cloudflare account. On the Workers Free plan, also > set `D1_DAILY_ROW_LIMIT` (see [Budget mode](https://checkend.com/docs/settings.md#budget-mode-workers-free-plan)). 1. Create a D1 database. Wrangler prints its `database_id`. ```sh npx wrangler d1 create checkend ``` 2. Copy `wrangler.jsonc` to `wrangler..jsonc`, for example `wrangler.mine.jsonc`. In the copy, set your Worker `name`, and add the `database_id` to the `DB` entry. Files with the name `wrangler.*.jsonc` are git-ignored, so your resource IDs stay out of the repository. 3. Apply the migrations and deploy: ```sh npx wrangler d1 migrations apply DB --remote --config wrangler.mine.jsonc npx wrangler deploy --config wrangler.mine.jsonc ``` 4. Set the admin token as a Worker secret. Until the secret is set, the API answers `401`. ```sh npx wrangler secret put ADMIN_TOKEN --config wrangler.mine.jsonc ``` For a project with many users, also add a rate limiting rule in front of ingest: see [Protect the ingest path](https://checkend.com/docs/sending-errors.md#protect-the-ingest-path). Apply the migrations before each deploy. Wrangler records each applied migration and skips it, so it is safe to run the command again. ## 3. Create a project and get a DSN A project is one app. Each project has a DSN: the address that the Sentry SDK sends errors to. **Figure: Create a project.** Running npm run project -- create --name "My App" --platform node prints: Created project 4821937065 (my-app). DSN: https://8c1f4d0e9b7a42f6a3e5d2c1b0f9e8d7@checkend.example.workers.dev/4821937065. Put the DSN in your Sentry SDK: Sentry.init({ dsn: "..." }). ```sh export CHECKEND_URL=https:// # or http://localhost:8787 export CHECKEND_ADMIN_TOKEN= npm run project -- create --name "My App" --platform node ``` The command prints the project ID and the DSN. To see all projects and their DSNs later: ```sh npm run project -- list ``` Add `--json` to either command for JSON output. **Figure: The parts of a DSN.** A DSN has the form https://@/, where the project ID is a random 10-digit public ID, for example https://8c1f4d0e9b7a42f6a3e5d2c1b0f9e8d7@checkend.example.workers.dev/4821937065. The public key is 32 hex characters. It identifies the project and only lets a client send events; it does not give read access. ## 4. Connect your app Use any Sentry SDK. Put the Checkend DSN in `Sentry.init`. For example, in Node: ```js import * as Sentry from "@sentry/node"; Sentry.init({ dsn: "https://@/" }); ``` Browser SDKs work too: the ingest endpoints allow requests from other origins (CORS). Checkend keeps **error events only** (exceptions and `captureMessage`). It drops sessions, transactions, client reports and attachments. See [Send errors](https://checkend.com/docs/sending-errors.md). ## 5. Read the errors ```sh curl -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" "$CHECKEND_URL/v1/issues" ``` Each issue is a group of events with the same cause. To see one issue and its events: ```sh curl -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" "$CHECKEND_URL/v1/issues/1" curl -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" "$CHECKEND_URL/v1/issues/1/events" ``` See [API](https://checkend.com/docs/api.md) for all endpoints. **Figure: Read the issues.** Example response of GET /v1/issues?limit=1 (formatted with jq): ```json { "data": [ { "id": 1, "project_id": 4821937065, "title": "TypeError: Cannot read properties of undefined (reading 'id')", "culprit": "loadUser (src/users.ts)", "type": "TypeError", "level": "error", "platform": "node", "status": "unresolved", "times_seen": 42, "stored_events": 42, "events_24h": 42, "events_7d": 42, "users_affected": 2, "priority": 198.462, "first_seen": "2026-10-10T14:02:11.087Z", "last_seen": "2026-10-10T15:47:03.412Z", "first_release": "my-app@1.4.0", "last_release": "my-app@1.4.0", "fingerprint": "5d41402abc4b2a76b9719d911017c592", "fingerprint_version": 1, "merged_into": null, "claim": null, "trust": "high" } ], "next_cursor": "WyIyMDI2LTEwLTEwVDE1OjQ3OjAzLjQxMloiLDFd", "ingest": { "mode": "full", "rows_written_today": 509, "daily_row_limit": null, "events_received_today": 42, "write_failures_today": 0, "retry_after_seconds": 0 } } ``` ## 6. Give your coding agent a read-only token Do not give the admin token to an agent. Create a token that can only read issues: ```sh curl -X POST "$CHECKEND_URL/v1/tokens" \ -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "claude-code", "scopes": ["issues:read"]}' ``` The response has the token (`ck_...`). Copy it now: Checkend shows it only once. Give it to the agent as its bearer token. To revoke it later, use `DELETE /v1/tokens/:id`. If the agent must also resolve, ignore or merge issues, create its token with `"scopes": ["issues:read", "issues:write"]`. ## 7. Connect your coding agent with MCP Add the Checkend MCP server to your agent with the read-only token. For Claude Code: ```sh claude mcp add --transport http checkend "$CHECKEND_URL/mcp" \ --header "Authorization: Bearer " ``` Then ask the agent, for example: "Fix the top unresolved error in Checkend." The agent calls `list_issues`, then `get_issue_brief`. See [MCP server](https://checkend.com/docs/mcp.md) for the tools and the issue brief. To let Checkend check in production that the fixes work, report your deploys. See [Verify fixes](https://checkend.com/docs/fix-loop.md). --- # Web UI Source: https://checkend.com/docs/web-ui (Markdown: https://checkend.com/docs/web-ui.md) > Checkend has a small web UI for people: sign in with a passkey, connect your apps, and read the errors. Coding agents keep the MCP server and the API. ## 1. Set up the first member The first person who signs in is the first **member**. Setup uses a one-time setup link: ```sh npm run setup-link -- --url https:// ``` The script asks `/health` whether setup is open. If it is, it stores a random code as the `SETUP_CODE` secret (with `wrangler secret put`) and prints the link `https:///setup#`. `npm run deploy` runs it after each deploy. Open the link, type your name, and create a passkey. Then setup closes for good. > **Note:** `ce server install` prints the setup link for every install (Cloudflare, Docker and > SSH). After a manual install on Node or Docker, the setup link is not available yet: use > development mode only on a local machine, or use `ce server install`. - The link works once, for 24 hours. Run `npm run setup-link` again for a new link. - The code is in the URL fragment, so the browser does not send it in a URL. - `/health` shows `setup_open: true` until the first member exists. - The `ADMIN_TOKEN` does not open the web UI. The web UI never uses bearer tokens. > **Caution:** a passkey works only on the host name where you made it. Make it on the host name > that people will use every day. Behind a proxy, set [`PUBLIC_URL`](https://checkend.com/docs/settings.md#public_url) first. More members, API tokens and releases in the web UI come in a later version. ## 2. Sign in Open `/login` and use your passkey. A session lasts 14 days. **Sign out** ends it. Each client gets at most 20 sign-in and setup tries in 15 minutes (then `429` `rate_limited`, with `Retry-After`). All clients together get at most 500. ## 3. Connect your apps **Home** (`/`) shows the setup prompt and a checklist for each app, until every app is set up. Then it opens the issues. **Copy prompt** makes a new [setup key](https://checkend.com/docs/agent-setup.md) and copies a prompt for your coding agent. Paste it in the repository of your app: ```text Set up Checkend error tracking for this app. 1. If `ce` is not installed, install it: https:///agent/install 2. Run `ce setup --url https://` with the setup key in the environment variable CHECKEND_SETUP_KEY. Never pass the key as an argument (--key), and never write it to a file, a commit or a log. 3. Follow the steps that `ce setup` prints. Setup key (valid for 1 hour): cks_… ``` The key is on a line of its own, not in a command. The agent passes it to `ce setup` only in `CHECKEND_SETUP_KEY`. > **Caution:** treat the prompt as a secret. Its setup key can add apps, send a test error, and > make agent tokens that read and change issues. **Apps** (`/apps`) lists your apps and their setup steps. Without a coding agent, use **Add an app**: type a name (1 to 100 characters) and a platform. The **manual** tab of the app then shows its DSN (the UI calls it the "app key") and the SDK setup. Each app shows its source and [trust](https://checkend.com/docs/sending-errors.md#trust-and-allowed-origins), on the Apps list and on its page: "Server SDK · High trust", "Browser · Low trust", "Mixed · Low trust", or "No events yet". "(set by hand)" means that an admin set the trust. The page of a low-trust app says how to improve it, and how to get its alerts again. To delete an app, type its name to confirm. When `REQUIRE_APPROVAL` contains `delete_project`, the delete waits for an [approval](https://checkend.com/docs/api.md#approvals). ## 4. Read the errors **Issues** (`/issues`) is the inbox, 50 issues on each page. Filter by app, status, environment, release, last seen (last hour, 24 hours, 7 days or 30 days), and text. The app filter shows only apps that are not deleted. An issue page shows the latest event, the last 20 events, the tags, and the source and trust of its app. An event page shows one event. The web UI shows event data as text: it never runs it as HTML. Each block of event data has the label "From your app" with an ⓘ: it explains that the data comes from the events of your app, that Checkend shows it as plain text and never runs it, and that agents treat it as data, not as instructions. ### Fix an issue and change its status An open issue (unresolved or regressed) has a **Fix this** block: - **Copy prompt for your agent** copies a prompt for your coding agent. The prompt names the issue by its ID and URL only, never by its title or event data, and it contains no secret. The agent reads the brief (`ce issue view ` or the MCP tool `get_issue_brief`), claims the issue (`claim_issue`), fixes it with a test, and links the fix (`link_fix`). - **Do it yourself with the CLI** shows the same steps as commands: `ce issue view `, and `curl` calls to claim the issue and link the fix. Put an API token with `issues:write` in `CHECKEND_TOKEN`. Every member can act on an issue. The page uses the same functions as the [API](https://checkend.com/docs/api.md), and the activity of the issue shows the member as the actor: | Action | Shown when | What it does | |---|---|---| | **Claim** | The issue is open and nobody holds a claim. | The signed-in member holds the claim for 2 hours. The page shows who holds a claim and when it expires. | | **Release** | You hold the claim. An owner can also release the claim of another actor, after a confirmation. | Ends the claim. | | **Resolve** | The issue is open. | Closes the issue by hand. A new event opens it again. | | **Ignore** | The issue is open. You confirm it first. | New events do not open the issue again. When `REQUIRE_APPROVAL` contains `ignore`, it waits for an [approval](https://checkend.com/docs/api.md#approvals). | | **Unresolve** | The issue is resolved or ignored. | Opens the issue again. | A manual **Resolve** is not a verified fix. Only Checkend verifies a fix: after a deploy that contains a linked fix, when the error stops for the quiet period (see [Verification](https://checkend.com/docs/fix-loop.md#verification)). An issue with a linked fix (`fix_pending`) or a verified fix has no status buttons. **Settings** shows `/health`, the ingest state, and the members with their passkeys. ## Tokens **Settings → Tokens** (`/settings/tokens`) makes API tokens, for example a token for CI. Only an owner can open it: on a self-hosted install, every member; in a hosted space, an owner. 1. Give the token a name. 2. Choose its scopes: `issues:read`, `issues:write` and `releases:write`. The page never makes an `admin` token. 3. Choose an app, or all apps. A token for one app reports deploys and uploads source maps only for that app. 4. Copy the token. Checkend shows it only once. The list shows the name, the scopes, the app, the first characters of each token, and when it was made and last used. **Revoke** stops a token at once, after a confirmation. ## A hosted space Checkend can also run as a hosted install: each space is one Checkend under its own path, on a shared host. In a hosted space: - you sign in and switch spaces with your account, outside the space. The space has no passkeys, no sign-in page and no setup link. - an owner can do everything. A member reads and changes issues and sets up apps, but cannot delete an app or make tokens. - the space updates itself: you do not run `ce server` or migrations. - the API, the DSNs, `ce` and MCP work as on a self-hosted install, with the URL of the space (for example `https:///`). ## Security - Sessions use a `__Host-` cookie (`HttpOnly`, `Secure`, `SameSite=Strict`). - Each form has a CSRF token, and each `POST` must come from the same origin. With `PUBLIC_URL`, the origin is `PUBLIC_URL`, else the origin of the request. - The body of each `POST` of the web UI is at most 1 MB, also with chunked bodies. Above that, the answer is `413` `{"error": "payload_too_large", "max_bytes": 1048576}`. - A strict Content Security Policy: no inline script or style. --- # Set up with an agent Source: https://checkend.com/docs/agent-setup (Markdown: https://checkend.com/docs/agent-setup.md) > A coding agent can set up Checkend in your apps for you: register each app, add the SDK, send a test event, and connect itself with MCP. You give it a short-lived setup key, and you can follow its progress. ## 1. Make a setup key In the [web UI](https://checkend.com/docs/web-ui.md#3-connect-your-apps), **Copy prompt** makes a setup key and a prompt for the agent. Or use the API: ```sh curl -X POST "$CHECKEND_URL/v1/setup/keys" \ -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" ``` A setup key (`cks_...`): - lasts 1 hour - works only on `/v1/setup/*`; on every other route it gets `401` - can register at most 10 apps and make at most 5 agent tokens, also with parallel requests; above that, the answer is `429` `{"error": "limit"}` - can be revoked with `DELETE /v1/setup/keys/:id`; this also revokes the agent tokens that it made Checkend stores only a hash of the key. `GET /v1/setup/keys` lists the keys. ## 2. Give the agent the recipe Tell the agent to read `https:///agent/install`, and give it the setup key. The recipes are public: they need no token and contain no secrets. | Path | What it is | |---|---| | `/agent/install` | Where the agent starts. | | `/agent/setup.md` | The setup steps. | | `/agent/tasks/.md` | Recipes for later tasks: `sourcemaps`, `deploys`, `migrate-from-sentry`, `environments`, `rotate-dsn`, `fix-top-issue`, `delete-project` and `remove`. | ## 3. What the agent does With the setup key (or an admin token), the agent: 1. Registers each app: `POST /v1/setup/apps` with `{"name": "...", "platform": "..."}`. It gets the project and its DSN (`201`). A retry with the same name returns the same app (`200`). 2. Makes an agent token for the app: `POST /v1/setup/tokens` with `{"name": "...", "project": ...}`. The token has `issues:read` and `issues:write`. 3. Adds the SDK with the DSN, and reports it: `POST /v1/setup/apps/:project/report` with `{"step": "sdk_installed"}`. 4. Sends one test event: `POST /v1/setup/apps/:project/test-event` (`202`). The event has the tag `checkend.test=true`. A second test event gives `409`. 5. Connects itself with [MCP](https://checkend.com/docs/mcp.md), with the agent token (see [Connect the agent](#connect-the-agent)). The test event makes a **test issue**. It is created resolved, and it does not count: it sends no alerts or webhooks, it adds nothing to the counts, the priority, the quotas or `last_event_at`, and it gets no AI triage. The issue list leaves it out (`GET /v1/issues?test=true` lists the test issues), and its brief has a row "Test event from setup: not a real error". ### Connect the agent The recipe connects the agent through `ce mcp`: a local MCP server that keeps the agent token in the keychain of the operating system, so the token never goes into a config file of the agent. Install `ce` (see [Install ce](https://checkend.com/docs/cli.md#install-ce) for npm, Homebrew and `go install`): ```sh curl -fsSL https://raw.githubusercontent.com/Checkend/checkend-cli/main/install.sh | sh ``` Then, for Claude Code: ```sh claude mcp add checkend -- ce mcp --url https:// ``` The agent starts `ce` by its name. If you used `go install`: it puts `ce` in `$(go env GOPATH)/bin` (or `$(go env GOBIN)`), which is often not on PATH. If `ce --version` fails, use the full path: ```sh claude mcp add checkend -- "$(go env GOPATH)/bin/ce" mcp --url https:// ``` Or add the folder to PATH in `~/.zshrc` or `~/.bashrc`: `export PATH="$PATH:$(go env GOPATH)/bin"`. Without `ce`, the recipe uses the fallback: HTTP MCP with the agent token in an environment variable (see [Connect](https://checkend.com/docs/mcp.md#connect)). The recipes take keys and tokens only from environment variables (`CHECKEND_SETUP_KEY`, `CHECKEND_TOKEN`, `CHECKEND_DEPLOY_TOKEN`, `CHECKEND_ADMIN_TOKEN`). > **Caution:** an agent token is install-wide. It can read and change the issues of every project > of the install, not only of its own app. It does not expire. The agent token stops working when you revoke its setup key (`DELETE /v1/setup/keys/:id`), when you delete its project, or when you revoke it (`DELETE /v1/tokens/:id`). Each revoked token gets a `token.revoke` activity row. The agent token that the setup made can also report the steps of its own app, also after the setup key expires. For any other app, it gets `403`. ## 4. Follow the progress `GET /v1/setup/progress` (with the setup key or an admin token) shows for each app: | Field | Meaning | |---|---| | `connected_at` | The app was registered. | | `sdk_installed_at` | The agent reported the SDK. | | `test_event_at` | The test event arrived. | | `first_event_at` | The first real event arrived (not the test event). | | `agent` | `{name, at}`: the first MCP call with the agent token, and the name of the MCP client. | | `first_deploy_at` | The first reported deploy. | It also shows `setup_keys_active`. A setup key sees only its own apps. See [Setup](https://checkend.com/docs/api.md#setup) in the API reference for all responses. --- # The ce CLI Source: https://checkend.com/docs/cli (Markdown: https://checkend.com/docs/cli.md) > ce is the command-line interface of Checkend, for people, scripts and coding agents. It has two names: ce (short) and checkend. On a terminal, it prints short tables and cards. When its output is not a terminal (an agent, a script, a pipe), or with --json, it prints the API JSON. The source and the full list of commands are in the [checkend-cli repository](https://github.com/Checkend/checkend-cli). ## Install ce `ce` is one binary for macOS, Linux and Windows. Install it with one of these. The install script: ```sh curl -fsSL https://raw.githubusercontent.com/Checkend/checkend-cli/main/install.sh | sh ``` npm (or run it once with `npx @checkend/cli`): ```sh npm install -g @checkend/cli ``` Homebrew (two commands: Homebrew does not tap on install): ```sh brew tap checkend/tap brew install checkend/tap/checkend ``` From source, with Go 1.26 or later: ```sh go install github.com/Checkend/checkend-cli/cmd/ce@latest ``` Then run `ce --version`. The install script and the npm package first check the SSH signature of the checksums of the release, then the SHA-256 of the binary. Without a valid signature, they install nothing. `go install` puts `ce` in `$(go env GOBIN)` when it is set, else in `$(go env GOPATH)/bin`. This folder is often not on PATH. If `ce --version` says "command not found", add the folder to PATH in `~/.zshrc` (zsh) or `~/.bashrc` (bash), then open a new terminal: ```sh export PATH="$PATH:$(go env GOPATH)/bin" ``` ## Update ce ```sh ce update ``` `ce update` looks for the newest release of `ce`, and it updates `ce` in the same way that you installed it: Homebrew, npm, the install script or `go install`. ## Log in ```sh ce login ``` `ce login` asks for the URL of your Checkend and an API token: a token from [Settings → Tokens](https://checkend.com/docs/web-ui.md#tokens), a token from [`POST /v1/tokens`](https://checkend.com/docs/api.md#post-v1tokens), or the `ADMIN_TOKEN` of a self-hosted install. It checks the URL and the token before it saves them. In CI or a script, give the token on stdin, never as an argument: ```sh echo "$CHECKEND_TOKEN" | ce login --url https:// --with-token ``` `ce logout` removes the saved token of the current instance. A saved token goes only to the URL that it was saved for. ## The keychain `ce` keeps tokens in the keychain of the operating system: the macOS Keychain, the Windows Credential Manager, or the Secret Service on Linux. The URL goes to `~/.config/checkend/config.json`. Without a keychain, the token goes to that file (mode 600), and `ce` tells you. Set `CHECKEND_NO_KEYCHAIN=1` to keep the token in the file. `ce setup` (see [Set up with an agent](https://checkend.com/docs/agent-setup.md)) saves the agent token of an app in the keychain too. `ce mcp` reads it from there, so the token never goes into a config file of the agent. `ce` never prints a token, and never writes one to `.checkend.json`. `.checkend.json` has the project link only, so you can commit it. ## Settings for all commands | Option | Environment | Meaning | |---|---|---| | `--url ` | `CHECKEND_URL` | Your Checkend. It can have a base path (a hosted space). | | `--token ` | `CHECKEND_TOKEN` | The API token. | | `--json` | | Print JSON, also on a terminal. | `ce` looks for a setting in this order: the option, the environment, `.checkend.json` (the project only), then the saved login. ## Install and manage a server `ce server` installs and manages a Checkend server that you run yourself: | Command | What it does | |---|---| | `ce server install cloudflare` | A Worker and a D1 database on your Cloudflare account | | `ce server install docker` | `compose.yaml` and `.env` for Docker on this machine | | `ce server install ssh --domain ` | An Ubuntu or Debian LTS server over SSH (see [On a server over SSH](https://checkend.com/docs/self-host.md#on-a-server-over-ssh)) | | `ce server upgrade` | Back up, then upgrade to a newer release | | `ce server backup` | Back up the database | | `ce server status` | The version, the health, and whether a newer release exists | | `ce server uninstall` | Remove the server. The data stays, unless you add `--delete-data`. | These commands install only a signed server release (see [Server releases](https://checkend.com/docs/operations.md#server-releases)). They show the plan and ask first (`--yes` for agents), and they end with the setup link of the web UI. The manual steps stay an alternative: [deploy to Cloudflare](https://checkend.com/docs/quick-start.md#2-or-deploy-it-to-your-cloudflare-account) or [run without Cloudflare](https://checkend.com/docs/self-host.md#with-docker). A hosted space does not use `ce server`: it updates itself. --- # MCP server Source: https://checkend.com/docs/mcp (Markdown: https://checkend.com/docs/mcp.md) > Checkend has an MCP server, so that a coding agent can find production errors and read an issue brief: a short, structured summary of an issue that has what the agent needs to fix it. ## Connect The MCP endpoint is `https:///mcp`. It uses the Streamable HTTP transport, and it is stateless. Each request needs a bearer token with the `issues:read` scope (or the `ADMIN_TOKEN`). Give the agent a read-only token, not the admin token: 1. Create a token with the `issues:read` scope. See [Quick start, step 6](https://checkend.com/docs/quick-start.md#6-give-your-coding-agent-a-read-only-token). 2. Add the server to your agent. For Claude Code: ```sh claude mcp add --transport http checkend https:///mcp \ --header "Authorization: Bearer " ``` For another MCP client, use the same URL and the same `Authorization` header. | Status | Body | Meaning | |---|---|---| | `401` | `{"error": "unauthorized"}` | The token is missing, not valid, or revoked. | | `403` | `{"error": "forbidden", "required_scope": "issues:read"}` | The token does not have the `issues:read` scope. | ## Tools The ID inputs (`issue_id`, `event_id` and `target_id`) accept a number or a string of digits, for example `42` or `"42"`. The lists `source_ids` and `event_ids` take numbers. ### `list_issues` Lists issues, the highest [priority](https://checkend.com/docs/api.md#priority-score) first. All inputs are optional: | Input | Values | |---|---| | `project` | The public project ID (10 digits) or the project slug. | | `status` | `unresolved`, `resolved` or `ignored`. | | `release` | Issues with this release (the first or last release of the issue, or a stored event). | | `environment` | Issues with a stored event in this environment. | | `since` | Issues last seen at or after this time: a duration (for example `30m`, `24h` or `7d`) or an ISO time. | | `search` | Text in the issue title or culprit. | | `claimed` | `true`: only claimed issues. `false`: only issues without an active claim. | | `sort` | `priority` (the default) or `last_seen`. | | `limit` | 1 to 100. The default is 10. | | `cursor` | The `next_cursor` from the previous result. | The result is JSON with `untrusted_notice`, `sort`, `issues` and `next_cursor`. Each issue has `id`, `project_id`, `status`, `level`, `times_seen`, `events_24h`, `users_affected`, `priority`, `first_seen`, `last_seen`, `claim`, `trust`, `source_trust` (the same as `trust`), `source` (`server`, `browser`, `mixed` or `null`) and `title_untrusted`. The first issue is the one to fix first. ### `get_issue_brief` Returns the [issue brief](#the-issue-brief) of one issue. Inputs: `issue_id`, and `format`: `markdown` (the default) or `json`. ### `get_event` Returns one event: the normalized event, with secrets removed (64 KB at most). Input: `event_id`. It never returns the raw payload. ### `resolve_issue` and `ignore_issue` Set the status of an issue to `resolved` or `ignored`. Input: `issue_id`. They return the issue as JSON. ### `split_issue` Moves 1 to 100 stored events of an issue to a new issue. Inputs: `issue_id` and `event_ids`. It returns the new issue. See [split](https://checkend.com/docs/api.md#post-v1issuesidsplit) for what a split does. It needs `issues:write`. ### `claim_issue`, `release_claim` and `add_note` - `claim_issue(issue_id, minutes?)` claims the issue, so that other agents do not work on it (see [claims](https://checkend.com/docs/api.md#claims-and-notes)). It returns the issue. When another agent has the claim, it gives a tool error, for example: "Issue 12 is claimed by agent-a until