npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tensorbuzz-api

v0.0.28

Published

JavaScript client for TensorBuzz error reporting with browser, Node, and Expo/React Native support.

Readme

tensorbuzz-api

JavaScript client for TensorBuzz error reporting with browser, Node, and Expo/React Native support.

Install

npm install tensorbuzz-api

Development and local file-dependency builds

This package is written in TypeScript and ships from its compiled build/ output (main/types point at build/). Building requires the dev dependencies (TypeScript) and is wired into the prepare lifecycle, so a normal npm ci/npm install in this directory installs the toolchain and builds automatically.

Sibling packages such as tensorbuzz-instance-control consume this package through a local file:../tensorbuzz-api reference. When npm prepares that local dependency it runs this package's prepare step without installing its devDependencies, so a plain tsc build would fail with tsc: not found. To keep the package installable from a clean checkout in that case while rejecting manifest/lockfile drift in every packaging path, prepare (scripts/prepare.mjs) runs npm ci --ignore-scripts before building. Use Node 24.x (the CI base image version).

Usage

import {BugReporting, debuggerInstance} from "tensorbuzz-api"

const bugReporting = new BugReporting({
  authToken: "your-token",
  projectId: "your-project-id",
  runtimeEnvironment: "browser"
})
bugReporting.connect()

You can add deployment/user context to every report:

bugReporting.collectEnvironment(() => ({
  release: "2026.05.19",
  runtime: "browser"
}))

bugReporting.collectParams(() => ({
  accountId: currentAccount?.id,
  userId: currentUser?.id
}))

handleError() resolves with the parsed TensorBuzz response when the report is accepted. Parameters and environment values from collectParams(), collectEnvironment(), error.tensorbuzzParameters, and error.tensorbuzzEnvironment are sanitized before posting: sensitive keys are redacted, long strings and large arrays are bounded, and binary/upload values are summarized without including bytes.

Applications that collect request bodies or other raw diagnostic metadata can reuse the same boundary helper:

import {sanitizeBugReportPayload} from "tensorbuzz-api"

const parameters = sanitizeBugReportPayload({
  body: requestBody,
  headers: requestHeaders
})

Project environment control

EnvironmentControlClient composes the public project-environment lifecycle, durable automation-supervisor command, and resumable command-event APIs. A service token must be scoped to the target account/project/environment and hold the corresponding project-environment and agent_runs read/write scopes.

import {EnvironmentControlClient} from "tensorbuzz-api"

const control = new EnvironmentControlClient({
  host: "https://server.tensorbuzz.com",
  serviceToken: process.env.TENSORBUZZ_API_TOKEN
})

const ensured = await control.ensureEnvironmentInstance({
  idempotencyKey: "deploy-task-42",
  projectEnvironmentId: "environment-id",
  reuse: true,
  reuseKey: "preview-main"
})

const dispatched = await control.dispatchCommand({
  idempotencyKey: "task-42-attempt-1",
  projectEnvironmentId: "environment-id",
  text: "Implement task 42"
})
const commandId = dispatched.projectEnvironmentAgentCommand.id
const stream = await control.streamCommandEvents({
  afterSequence: loadCheckpoint(commandId),
  commandId,
  onEvent: (event, afterSequence) => {
    consumeRedactedEvent(event)
    saveCheckpoint(commandId, afterSequence)
  }
})
const terminalStatus = await control.waitForCommand({commandId})
await stream.close()

Persist the numeric afterSequence supplied to onEvent and provide it on the next subscription. Reconnect delivery is at-least-once, and the client suppresses events at or below its current checkpoint. Event callbacks may be asynchronous; the client processes them in order and advances only after each callback succeeds. If a callback fails, the subscription closes and stream.done rejects so the caller can reconnect from its last durable checkpoint. Pending callback delivery is capped at 1,000 events; overflow also fails closed for cursor-safe reconnect. The CLI honors stdout backpressure before advancing each event. The service token is sent as an HTTP header or transient WebSocket session metadata; it is never placed in command payloads, URLs, cursor parameters, or output. Event and status content retains the server's public redaction and size bounds. The client deliberately exposes no provider selection, worker/terminal session, or raw shell controls.

Controlling error message and backtrace inclusion

By default every report includes the original error message and backtrace. To include those raw values only for trusted requests, pass shouldIncludeErrorDetails — either a boolean or a callback returning boolean | Promise<boolean>:

const bugReporting = new BugReporting({
  authToken: "your-token",
  projectId: "your-project-id",
  shouldIncludeErrorDetails: (context) => context.environment?.isAdmin === true
})

The callback receives the report/policy context: {error, errorClass, message, backtrace, url, httpMethod, requestBody, environment, parameters, hostname, runtimeEnvironment}. Surface trusted request/user metadata for decisions such as "current user is an admin" or "request IP is allowlisted" through the environment/parameters you already provide via collectEnvironment(), collectParams(), error.tensorbuzzEnvironment, or error.tensorbuzzParameters.

  • Default is true (include message and backtrace), preserving previous behavior.
  • When the policy denies (or is false), the report omits both message and backtrace while keeping the safe metadata needed for grouping and diagnostics (error_class, url, http_method, user_agent, parameters, environment, requestBody).
  • The callback may be synchronous or asynchronous; it is awaited before the report is serialized and sent.
  • If the callback throws or rejects, evaluation fails closed (details are omitted) and never propagates out of the reporting path, so a broken policy cannot break the host application.

Request transport

By default, BugReporting uses XMLHttpRequest when available, otherwise it falls back to fetch. If neither is available, you must provide a request class.

import {BugReporting, NodeRequest} from "tensorbuzz-api"

const bugReporting = new BugReporting({
  authToken: "your-token",
  projectId: "your-project-id",
  hostname: "api.example.com",
  postUrl: "https://server.tensorbuzz.com/errors/reports",
  runtimeEnvironment: "node",
  RequestClass: NodeRequest
})

Browser error listeners

import {BugReporting} from "tensorbuzz-api"

const bugReporting = new BugReporting({authToken: "your-token", projectId: "your-project-id"})

// Optional: enable source map parsing for script tags in web apps.
bugReporting.enableSourceMapsLoader()

bugReporting.connectOnError()
bugReporting.connectUnhandledRejection()

Browser bug reporter (hardened)

Browser hosts that need stricter guarantees than connect() — an allowlisted wire payload, URL/text redaction, bounded symbolication, breadcrumbs, and Error-identity dedupe — use initializeBrowserBugReporting from the bug-reporting subpath:

import {initializeBrowserBugReporting} from "tensorbuzz-api/build/bug-reporting/browser-reporter.js"
import SourceMapsLoader from "tensorbuzz-api/build/bug-reporting/source-maps-loader.js"

const reporter = initializeBrowserBugReporting({
  browser: window,
  configuration: {
    applicationEnvironment: "production",
    authToken: "your-token",
    projectId: "your-project-id",
    postUrl: "https://server.tensorbuzz.com/errors/reports",
    release: "2026.05.19"
  },
  sourceMapsLoader: new SourceMapsLoader({browser: window, loadScriptTagMaps: false})
})

if (reporter) {
  window.addEventListener("beforeunload", () => reporter.disconnect())
}

initializeBrowserBugReporting returns null when the host configuration does not opt in: applicationEnvironment must be "production" or "staging", authToken and projectId must be non-empty strings, the browser context must provide fetch and AbortController, the optional host runtime flag RAILS_ENV must not be "development" or "test" when defined, and a configured postUrl must be an https: URL without credentials, query, or fragment. Each call returns a fresh reporter that wires its own window error, unhandledrejection, popstate, hashchange, and document click listeners; the host owns one reporter per browser and calls disconnect() to remove them. Reports are sent with credentials: "omit", referrerPolicy: "no-referrer", redirect: "error", and a 5 second deadline that aborts the request and fails the report when it expires. The same Error object is reported once, cause chains are bounded, and failed reports release the dedupe so later reporting recovers.

The transport-boundary sanitizers are exported from tensorbuzz-api/build/bug-reporting/browser-sanitize.js:

import {safeText, safeUrl} from "tensorbuzz-api/build/bug-reporting/browser-sanitize.js"

safeText strips URL credentials, redacts data:/blob:/javascript: URLs, and drops query/hash fragments except a stack frame's trailing :line(:col) coordinates. safeUrl returns only origin and pathname (bounded to 500 characters) for http(s) URLs, or null otherwise.

SourceMapsLoader browser context

SourceMapsLoader accepts optional constructor options for browser-safe map loading:

new SourceMapsLoader({
  browser,
  loadScriptTagMaps: false,
  maxConcurrentLoads: 4,
  maxCachedMaps: 64,
  perMapTimeoutMs: 3000,
  symbolicationBudgetMs: 3000
})
  • browser is an injected context whose members (document, fetch, XMLHttpRequest, AbortController, setTimeout, clearTimeout) each fall back to the matching globalThis member.
  • When browser.fetch is a function, maps are loaded with a private fetch (GET, credentials: "omit", referrerPolicy: "no-referrer", redirect: "error") with per-map abort timeout and in-flight dedupe. When browser also provides document and location, maps are only resolved for https /packs/*.js URLs on the page origin or the origins of the page's https /packs/ script tags.
  • At most maxConcurrentLoads maps load at once (further sources are skipped, not queued), new loads stop once maxCachedMaps maps are cached, and loadSourceMaps(error) never waits longer than symbolicationBudgetMs; pending loads keep running and their maps are reused by later errors.
  • loadScriptTagMaps: false loads only stack-referenced maps instead of every script tag.
  • Browser 1-based columns are converted to 0-based for source-map lookups and back for output, and unparseable stacks fall back to the raw stack instead of no frames.
  • No-arg construction preserves the legacy XMLHttpRequest behavior exactly.

Node error listeners

import {BugReporting, NodeRequest} from "tensorbuzz-api"

const bugReporting = new BugReporting({
  authToken: process.env.TENSORBUZZ_BUG_REPORT_AUTH_TOKEN,
  hostname: process.env.TENSORBUZZ_BUG_REPORT_HOSTNAME,
  projectId: process.env.TENSORBUZZ_BUG_REPORT_PROJECT_ID,
  runtimeEnvironment: "node",
  RequestClass: NodeRequest
})

bugReporting.connectNodeFatalHandlers()

The Node fatal handlers are coordinated process-wide, including when multiple reporter instances are connected. The first uncaught exception or unhandled rejection gets one bounded reporting attempt, then the process terminates with exit status 1 whether reporting succeeds, fails, or hangs. Nested fatal events do not start more reports or extend the exit deadline. The existing connectNodeUncaughtException() and connectNodeUnhandledRejection() methods remain available for compatibility.

Instance control audits

import {InstanceControlAudits} from "tensorbuzz-api"

const instanceControlAudits = new InstanceControlAudits()

await instanceControlAudits.report({
  emittedAt: new Date().toISOString(),
  eventType: "action_cable.subscription.rejected",
  instanceControlToken: "instance-control-token",
  level: "error",
  message: "ProjectEnvironmentTerminalSessionsChannel subscription rejected",
  metadata: {attempt: 3},
  postUrl: "https://server.tensorbuzz.com/errors/instance_control_audits",
  projectEnvironmentInstanceId: "instance-id",
  projectEnvironmentTerminalSessionId: "terminal-session-id",
  projectId: "project-id"
})

Expo / React Native error listeners

import {BugReporting} from "tensorbuzz-api"

const bugReporting = new BugReporting({authToken: "your-token", projectId: "your-project-id"})

bugReporting.connectExpoErrorHandlers()

Direct reporting endpoint

Non-JavaScript runtimes can post JSON directly to /errors/reports. The error.parameters, error.environment, and top-level metadata fields can be JSON objects or JSON strings; TensorBuzz parses, sanitizes, and bounds them before storing the bug-report instance.

await fetch("https://server.tensorbuzz.com/errors/reports", {
  body: JSON.stringify({
    auth_token: "your-token",
    projectId: "your-project-id",
    hostname: "app.example.test",
    runtimeEnvironment: "browser",
    error: {
      backtrace: ["Error: boom", "at checkout.js:10:4"],
      environment: {release: "2026.05.19"},
      error_class: "CheckoutError",
      message: "Checkout failed",
      parameters: {orderId: "ord_123"},
      url: "https://app.example.test/checkout",
      user_agent: navigator.userAgent
    }
  }),
  headers: {"Content-Type": "application/json"},
  method: "POST"
})

CLI

npx tensorbuzz-api login
npx tensorbuzz-api build-logs --latest-build-group --failing
npx tensorbuzz-api environment-instance readiness --project-environment ENVIRONMENT_ID
npx tensorbuzz-api environment-instance ensure --project-environment ENVIRONMENT_ID --idempotency-key TASK_KEY
npx tensorbuzz-api environment-instance inspect --instance INSTANCE_ID
npx tensorbuzz-api environment-command dispatch --project-environment ENVIRONMENT_ID --idempotency-key TASK_KEY --text "Implement task 42"
npx tensorbuzz-api environment-command status --command-id COMMAND_ID
npx tensorbuzz-api environment-command wait --command-id COMMAND_ID --timeout-ms 300000
npx tensorbuzz-api environment-command events --command-id COMMAND_ID --after-sequence 41
npx tensorbuzz-api environment-command cancel --command-id COMMAND_ID
npx tensorbuzz-api webhook-watcher list
npx tensorbuzz-api webhook-watcher register-ci --thread-id THREAD_ID --chat-id CHAT_ID --project-id PROJECT_UUID --pr-number PR_NUMBER --build-group-id BUILD_GROUP_ID --prompt "Resume the task, inspect this completed build group, and continue from its verified result."

For a durable CI + PR-review continuation, use the transactional continuation flow. It creates separate opaque build, review, and PR-lifecycle callback paths and preserves both persistent PR watchers when the exact head/build-group gate is replaced:

npx tensorbuzz-api webhook-watcher register-continuation --thread-id THREAD_ID --chat-id CHAT_ID --repository OWNER/NAME --project-id PROJECT_UUID --pr-number PR_NUMBER --build-group-id BUILD_GROUP_ID --head-sha HEAD_SHA

The chat ID must be an exact decimal Telegram ID (negative group IDs are supported) and the thread/topic ID must be a positive decimal integer. Composite values such as CHAT_ID:THREAD_ID, whitespace-corrupted values, and zero are rejected before the API or route store is accessed. Before activation, the command reads Project, BuildGroup, and Build association and calls the BuildGroup.currentPullRequestGeneration read contract. That contract resolves the live GitHub PR head through the linked GitHub App and requires exactly one project/PR build group containing it, so a retained historical generation, missing generation, or ambiguous mapping fails before provider or route-store mutation. The supplied head and build-group are treated as event hints: the returned GitHub-authoritative generation is re-read and verified before any replacement activates. Reordered, duplicate, or skipped synchronize claims therefore converge to the live head instead of moving monitoring backward.

The continuation's persistent review callback uses the deployed TensorBuzz provider event set: github.pr_review.submitted, github.pr_review_comment.created, github.pr_review_thread.changed, github.pr_review.readiness_changed, and github.pr_review.activity_after_merge. Exact provider readback must return that same event set before registration becomes active.

Both new and idempotent registrations print one stable, secret-free JSON receipt. It contains the exact binding, all three opaque route names and provider subscription IDs, their event and lifecycle contracts, and proof claims showing an accepted nonduplicate first delivery followed by an accepted same-ID duplicate. Any continuation-flow failure is nonzero and includes UNMONITORED — registration incomplete plus a stable safe reason code. Receipts and errors never include the signing secret, token, signature, request headers, payload body, or credential path.

The webhook-watcher command also supports list, remove, cleanup-orphans, and test. list includes both legacy named watchers and opaque continuation routes, including each continuation role, registration state, expected head, owning project, provider subscription ID, and a conservative route classification. Versioned continuation routes are schema-validated before any mutation. Malformed legacy records remain read-only inventory: they are neither coerced into the managed schema nor silently deleted. An exact active pre-schema continuation pair is adopted in place only after both provider IDs, scopes, lifecycles, and signed ingress proofs succeed; partial, conflicting, or ambiguous legacy state fails UNMONITORED without creating replacements. An exact legacy pair is completed with the separate lifecycle callback during the same command. Route readback also requires deliver_only: false; notification-only records cannot claim an agent-capable continuation. Matching active strict routes must have unambiguous build/review/lifecycle cardinality. Partial current-generation, duplicate, or mixed-role state fails closed without provider mutation; exact persistent review and lifecycle routes from an earlier generation remain eligible for exact readback and reuse during the next build-generation registration. Route updates reload and compare the store immediately before atomic replacement, and compensation removes or restores only routes still exactly owned by the failed registration, so unrelated concurrent additions survive. Every remote create is write-ahead recorded on its provisional route before activation; after a crash, registration resolves a missing opaque provider ID by that route's random URL, resumes missing roles, and compensates stale attempts without manual database edits. Run cleanup with an explicit cleanup-orphans --project-id PROJECT_UUID; it applies only to routes persisted for that project. Before cleanup, legacy routes without stored project ownership are read back from the provider: a route is backfilled only when that readback proves exact ownership by the requested project. A backfilled completed one-shot route can then be removed. Routes owned by other projects, plus legacy routes with missing, ambiguous, malformed, or inaccessible provider readbacks, are retained conservatively because a project-scoped token cannot prove they are missing. Unrelated Hermes routes are also untouched. Set TENSORBUZZ_API_TOKEN when using commands that access the TensorBuzz API. The token used for continuation registration needs projects:read and webhooks:manage; no broader scope is required. It should be scoped to the single target project. Configure HERMES_WEBHOOK_SIGNING_SECRET through the deployment secret store so registration can safely bootstrap an empty HERMES_WEBHOOK_SUBS_PATH; the secret is never recovered by restoring old route records. Existing installations without that variable retain their route-level secret fallback for compatibility.

Continuation registration first persists all needed local routes as one provisional attempt. After each createCallback, it records the returned opaque ID on that route, reads the callback back through the same authenticated frontend-model API, and requires exactly one active record matching the intended project, PR, build group, events, callback URL, and lifecycle flags. It proves all signed ingress routes before one atomic activation. Missing, ambiguous, or unrelated records are rejected and compensated through the authenticated destroy command; a retry can also recover an unrecorded ID from the attempt's opaque callback URL.

If an otherwise reusable persistent review or lifecycle route returns 404 during public ingress proof, continuation registration first reads back the exact old provider ID, deactivates that exact callback, marks the local route stale, and only then creates a replacement. It never bulk-deletes ambiguous, provider-only, local-only, no-topic, no-provider-ID, or cross-project records.

register-ci and register-review create agent-capable Hermes routes by default. Incoming TensorBuzz events therefore start an agent continuation as well as targeting the configured Telegram chat/thread. For meaningful autonomous workflows, pass a self-contained --prompt that identifies the task and tells the agent what evidence to inspect and what continuation to perform. Without --prompt, the watcher preserves its concise payload-aware default (TensorBuzz: {buildGroup.name} — {buildGroup.status} or the equivalent build text). Empty or whitespace-only prompts are rejected before creating a subscription. Use --deliver-only explicitly when the route should send only a Telegram notification and must not start an agent continuation.

register-ci has a deliberately fixed contract: it requires the exact project, PR, and build-group identifiers, subscribes only to build_group.completed, and creates a one-time callback that auto-deletes after successful delivery. It does not accept per-build events or lifecycle overrides.

register-review is separate and persistent. It requires the exact project and PR plus an explicit comma-separated --events selection from github.pr_review.submitted, github.pr_review_comment.created, and github.pr_review_thread.changed. Review callbacks are never one-time or auto-deleting. Both commands read the exact returned provider subscription ID back and verify all non-secret scope and lifecycle fields before replacing the local route.

webhook-watcher test --route-name NAME copies the selected route to a temporary, non-one-shot test route, sends a correctly signed semantic delivery, replays the same delivery ID to verify duplicate handling, and removes the test route. It never sends synthetic traffic through the live CI route. It supports build_group.completed, all five continuation review events, and all three PR lifecycle events listed above, choosing the route's first event. Test traffic includes tensorbuzzRegistrationProof: true; the receiver must authenticate it and handle it as proof only, before notification, agent dispatch, or one-shot consumption. Do not run this against a gateway whose proof-only handling has not been verified in isolation.

Both test and registration proof require JSON objects with an exact delivery_id match and status: "accepted" on each 2xx response. The first claim must have boolean duplicate: false; its identical replay must have boolean duplicate: true. Text containing "accepted", "ok", or "duplicate" is not proof. The test command prints only this allowlisted receipt (never gateway bodies):

{"status":"ok","delivery_id":"<test-delivery-id>","signed":true,"first":{"accepted":true,"duplicate":false},"replay":{"accepted":true,"duplicate":true}}

signed: true means the client signed the requests, not that a receiver's signature enforcement has been independently proven. Registration uses X-Webhook-Signature-V2 over timestamp.rawBody; test uses the actual outbound raw-body HMAC contract with both TensorBuzz-native and GitHub-compatible headers. A timestamped proof does not substitute for raw-body signature verification. test does not read the provider or prove the complete monitoring binding.

The host must invoke an explicitly pinned, built package CLI through a thin credentials/store adapter, not streamed source. Package tests with mocked fetch responses are client-contract tests, not evidence that the real host sees dynamic routes or suppresses proof dispatch. See the repository's docs/webhook-callback-lifecycle.md for receiver coverage, post-push gating, and approval-gated cutover/rollback.

login uses browser approval by default: it prints a TensorBuzz URL, you approve the request while signed in (including GitHub-authenticated users), and the CLI stores credentials automatically.

The CLI stores credentials in .tensorbuzz-api/credentials.json at the git root and uses the current branch by default.

Agent runs

agent-run uses the documented raw frontend-model API and a scoped service token. Set the server and token in the environment so the secret does not enter shell history:

export TENSORBUZZ_API_URL=https://server.tensorbuzz.com
export TENSORBUZZ_API_TOKEN=your-scoped-service-token

The token needs the scopes appropriate to each operation (commonly projects:read, agent_runs:read, agent_runs:write, environments:write, builds:read, and builds:write). The CLI also accepts --host and --service-token; it never prints the token. A serviceToken stored alongside host in .tensorbuzz-api/credentials.json is supported for unattended installations.

Check readiness and start a planning-first run:

npx tensorbuzz-api agent-run readiness --project-environment ENVIRONMENT_ID --json
npx tensorbuzz-api agent-run start \
  --project-environment ENVIRONMENT_ID \
  --goal "Implement task TB-42" \
  --source-system jira \
  --source-project-id PROJECT_KEY \
  --source-task-id TB-42 \
  --source-url https://jira.example/browse/TB-42 \
  --idempotency-key jira-TB-42

start requires plan approval by default. Only pass --plan-approval-policy auto when the automation is explicitly authorized to execute without owner approval. Source metadata is accepted as a JSON object with --source-metadata '{"priority":"high"}'.

Supervise the resulting run:

npx tensorbuzz-api agent-run status --run-id RUN_ID
npx tensorbuzz-api agent-run logs --run-id RUN_ID --limit 200 --json
npx tensorbuzz-api agent-run send-message --run-id RUN_ID --message "Approved" --decision approve_plan
npx tensorbuzz-api agent-run resume-from-source --run-id RUN_ID --source-event-id COMMENT_ID --source-task-id TB-42 --planning-revision 1 --message "Include CSV export" --decision request_plan_changes
npx tensorbuzz-api agent-run verify --run-id RUN_ID --branch-name agent/run-RUN_ID
npx tensorbuzz-api agent-run failure-context --run-id RUN_ID --json
npx tensorbuzz-api agent-run retry --run-id RUN_ID --reason "Verification failed" --failed-command "npm run typecheck" --prompt "Fix and verify again"
npx tensorbuzz-api agent-run cancel --run-id RUN_ID --reason "Superseded"

Use the returned nextCursor as --cursor for the next log page. --limit is bounded to 1–1000. --json writes only the command response as one compact JSON line for reliable scripting; human output stays concise.

For manual token login, pass --auth-token (or TENSORBUZZ_API_AUTH_TOKEN):

npx tensorbuzz-api login --host https://tensorbuzz.example --repo owner/name --auth-token your-project-auth-token

For legacy password login, pass --password (and optionally --email, or TENSORBUZZ_API_EMAIL / TENSORBUZZ_API_PASSWORD):

npx tensorbuzz-api login --host https://tensorbuzz.example --repo owner/name --email [email protected] --password your-password

Persistent review watcher

Register a persistent observer with an explicit supported review-event set:

npx tensorbuzz-api webhook-watcher register-review \
  --thread-id THREAD_ID --chat-id CHAT_ID --project-id PROJECT_UUID \
  --pr-number 42 \
  --events github.pr_review.submitted,github.pr_review_comment.created