Menu

Choose a theme and configure high-contrast mode. Preferences are saved in your browser only.

User preferences

Theme

Pick a palette or follow your system preference.

High contrast

Sharper text and borders. System follows your OS setting.

Copy page

Set up Bicho

Set up Bicho on Cloudflare Workers, create your first project, and connect your app. Follow the deployment guide to capture and investigate production errors.

Bicho is an error tracker you run in your own Cloudflare account. A Worker accepts exception and error logs, D1 indexes them as issues, and a private R2 bucket stores the captured evidence. You investigate through MCP or the HTTP API. Bicho doesn’t include a dashboard, and you don’t need an OpenTelemetry Collector.

Start by deploying the server and creating a project. Then connect the application you want to monitor. The server and application SDKs are separate packages; installing an SDK doesn’t deploy a server.

Deploy the server

You need a Cloudflare account with R2 enabled. The hosted setup doesn’t require a local checkout.

Deploy Bicho to Cloudflare.

The deployment flow copies the server repository into your account, provisions D1 and R2, and sets up Workers Builds. Its deploy command applies database migrations before deploying the Worker.

When prompted for BICHO_ADMIN_TOKEN, provide a unique token. Generate one on your own machine:

openssl rand -hex 32

Save it in a password manager. The server uses this token for API reads, project creation, source-map uploads, issue status changes, and instance MCP access. Keep it in a Cloudflare Worker secret, never in frontend code, D1, or a public configuration file. An unset or empty token makes admin endpoints return HTTP 503.

When the build finishes, save the Worker’s https://<your-worker>.<your-subdomain>.workers.dev address. This is your collector’s base URL. It isn’t https://bicho.fyi, which hosts this documentation rather than your errors.

Connect MCP

Add your instance to a client that supports Streamable HTTP and custom headers. Clients use different configuration formats; this example fits clients with an mcpServers URL configuration:

{
  "mcpServers": {
    "bicho": {
      "url": "https://your-bicho-worker.example/mcp",
      "headers": {
        "Authorization": "Bearer <admin-token>"
      }
    }
  }
}

Replace the hostname and token with your own values. The MCP guide covers transport requirements and available tools.

You can also connect the public documentation MCP for help with setup. It doesn’t need a token and cannot see or administer your instance. Never send your instance credentials to it.

Create a project

Use one project for each application or boundary you want to investigate separately. First call list_projects to see what’s already registered. Then call create_project with:

{
  "name": "My app",
  "hourly_limit": 1000,
  "secret": false
}

Only name is required. hourly_limit accepts an integer from 1 to 1000000 and defaults to 1000 new events per UTC hour. Set secret: false for browser applications, the current JavaScript SDK, and both modes of the Astro integration. The PHP, Rust, and Python SDKs and backend exporters can use secret: true to require an additional ingest secret.

The response contains:

  • project.id: a generated numeric-string identifier for API and MCP reads.
  • otlp.endpoint: your instance’s /v1/logs endpoint.
  • otlp.headers: X-Bicho-Key, plus X-Bicho-Secret for a secret-enabled project.
  • sentry.dsn: the DSN for an existing Sentry SDK. Secret-enabled projects also return sentry.headers for the backend transport.

Save the returned ingest headers and Sentry DSN immediately. Project listings don’t return credentials, and the server stores only a hash of an ingest secret. Every creation call makes a new project, even if the name matches an existing one. Check the project listing before retrying after a lost response. Bicho doesn’t provide a credential recovery or rotation endpoint.

If you prefer HTTP, send the same JSON to POST /api/projects with your admin bearer token. See the HTTP API reference.

Connect your application

Already using Sentry? Keep your SDK and replace its DSN with the generated sentry.dsn. Disable unsupported integrations; secret-enabled backend projects also require the generated transport headers.

Choose a Bicho SDK for your application:

  • JavaScript/TypeScript and Node.js: automatic browser capture and explicit Node.js reporting.
  • PHP: explicit exception/message capture with synchronous delivery.
  • Rust: explicit error/message capture with awaited delivery on Tokio, including Tauri applications.
  • Python: explicit exception/message capture with synchronous delivery on Python 3.11+, using only the standard library.
  • Astro: opt-in browser capture and SSR request-exception reporting, with separate project configuration.

For other languages or existing instrumentation, use an OTLP/HTTP logs exporter; Bicho accepts JSON and binary protobuf logs.

The runnable Bicho examples cover browser, Node.js, PHP, Rust, Python, and Sentry on Node.js. Use a dedicated test project: running an example creates real error reports.

For a browser application:

npm install @bicho-fyi/javascript

Initialize in your browser entry point with the returned endpoint and otlp.headers['X-Bicho-Key']:

import * as Bicho from '@bicho-fyi/javascript';

Bicho.init({
  endpoint: 'https://your-bicho-worker.example/v1/logs',
  key: 'YOUR_PUBLIC_KEY',
  serviceName: 'my-app',
  environment: 'production',
  release: 'my-app@1.0.0',
});

This captures uncaught browser errors and unhandled promise rejections after initialization. The public key identifies the project; serviceName is application metadata, not authentication. The current JavaScript SDK doesn’t send X-Bicho-Secret, including when used in Node.js. Never put an ingest secret or admin token in a browser bundle.

See SDKs and integrations to choose a client. Configuring an OTLP exporter doesn’t itself capture exceptions; your instrumentation must emit them as logs.

Check the result

Send a clearly named setup event from your application:

Bicho.captureMessage('Bicho setup check');
const delivered = await Bicho.flush(5000);

This creates a real error-level occurrence in the project. Use a dedicated test project if you don’t want setup events in your production history. captureMessage() returning a UID means queued, not delivered. A successful flush() confirms the SDK’s delivery result, not that a particular issue was found.

Call search_issues with your generated project_id. Open the matching result with get_issue, then use get_event with a returned event ID to read its evidence. Check the message, service and environment. The SDK’s occurrence UID isn’t the server event ID.

If nothing appears, see troubleshooting. Resolving a test issue hides it from the default unresolved listing but doesn’t delete its events.

Local development

Use Node 24 and npm. Clone the server, install dependencies, and copy the example environment file:

git clone https://github.com/bicho-fyi/bicho.git
cd bicho
nvm use
npm ci
cp .dev.vars.example .dev.vars

If you don’t use nvm, install Node 24 another way and skip nvm use. Edit the ignored .dev.vars file to set BICHO_ADMIN_TOKEN to a fresh random token. Keep the value private.

Apply the schema to local D1, then start the Worker:

npx wrangler d1 migrations apply DB --local
npm run dev

Connect MCP at http://localhost:8787/mcp, or register a project through POST http://localhost:8787/api/projects, using the local admin token. Use the local project’s generated endpoint and headers in your application. Local D1 and R2 state are separate from hosted resources; a project created locally doesn’t exist on the hosted instance.

For development checks, run npm run check and npm test in the server repository. The test suite uses isolated local storage and doesn’t send errors to a hosted instance.

Manual hosted setup

Use this route if you already manage your Cloudflare resources or CI configuration:

  1. Provision a D1 database and private R2 bucket. In the server’s wrangler.jsonc, replace the placeholder D1 ID and choose your resource names. The defaults are Worker/database bicho and bucket bicho-events.
  2. Keep the D1 binding named DB, the R2 binding named PAYLOADS, the nodejs_compat flag, and migrations_dir: "migrations".
  3. Configure BICHO_ADMIN_TOKEN as a Worker secret. Leave CORS_ORIGINS empty unless you need trusted browser origins for admin access; ordinary cross-origin ingestion already supports preflight. See credentials and privacy.
  4. Set your Workers Builds or CI/CD deploy command to npm run deploy. It applies remote migrations through the DB binding before deploying.
  5. Check that the hourly Cron Trigger, 0 * * * *, is attached. It resumes source-map processing when request-triggered work leaves a backlog.
  6. Create a project on the hosted instance through its API or MCP, then configure your application with those credentials.

The initial migration targets a fresh database. Editing a migration that already ran doesn’t upgrade that database. Don’t reset populated storage to reapply it.

For a custom domain, configure the Worker route and disable workers_dev when you no longer need the alternate URL. Preview URLs are disabled by default. Apply WAF and rate limiting rules to the entry points you actually expose; don’t use interactive challenges on ingest, API, or MCP paths. Operations and limits covers quotas, monitoring, and storage growth.

Offline project generation

The server includes an optional generator for setups where you manage project SQL yourself:

npm run project -- 1 "My app" http://localhost:8787
npx wrangler d1 execute DB --local --file=_temp/project-1.sql

Run these commands in the server repository after applying the schema. Choose an unused positive numeric project ID. The generator writes _temp/project-1.sql and _temp/project-1.json without contacting Cloudflare; it won’t overwrite existing files. Applying the SQL registers the local project. Read its generated otlp object from the JSON file to configure ingestion.

The generator also accepts --hourly-limit=1000 and --secret. For a hosted project, generate against the hosted origin and deliberately apply the SQL to the remote database instead. Generating or editing a JSON file doesn’t register anything. API or MCP creation is usually simpler and generates the project ID for you.

Keep generated SQL and JSON private: they contain ingest credentials. The repository’s project.example.json and project.example.sql contain placeholders, not credentials you can use.

Type to search the documentation.